aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/ClangFormatStyleOptions.rst9
-rw-r--r--docs/CrossCompilation.rst2
-rw-r--r--docs/LanguageExtensions.rst10
-rw-r--r--docs/PCHInternals.rst26
-rw-r--r--docs/UsersManual.rst39
-rw-r--r--include/clang-c/BuildSystem.h12
-rw-r--r--include/clang/AST/ASTContext.h30
-rw-r--r--include/clang/AST/DataRecursiveASTVisitor.h33
-rw-r--r--include/clang/AST/DeclObjC.h292
-rw-r--r--include/clang/AST/ExprObjC.h38
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h32
-rw-r--r--include/clang/AST/Type.h296
-rw-r--r--include/clang/AST/TypeLoc.h118
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h2
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h3
-rw-r--r--include/clang/ASTMatchers/Dynamic/VariantValue.h6
-rw-r--r--include/clang/Basic/Attr.td10
-rw-r--r--include/clang/Basic/AttrDocs.td19
-rw-r--r--include/clang/Basic/BuiltinsPPC.def46
-rw-r--r--include/clang/Basic/BuiltinsX86.def60
-rw-r--r--include/clang/Basic/DeclNodes.td1
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticGroups.td1
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td16
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td99
-rw-r--r--include/clang/Basic/IdentifierTable.h4
-rw-r--r--include/clang/Basic/LangOptions.def1
-rw-r--r--include/clang/Basic/Sanitizers.h21
-rw-r--r--include/clang/Basic/TargetInfo.h16
-rw-r--r--include/clang/Basic/TokenKinds.def5
-rw-r--r--include/clang/CodeGen/ObjectFilePCHContainerOperations.h43
-rw-r--r--include/clang/Driver/Action.h57
-rw-r--r--include/clang/Driver/CLCompatOptions.td6
-rw-r--r--include/clang/Driver/Driver.h4
-rw-r--r--include/clang/Driver/Job.h3
-rw-r--r--include/clang/Driver/Options.td46
-rw-r--r--include/clang/Driver/SanitizerArgs.h1
-rw-r--r--include/clang/Driver/Types.def1
-rw-r--r--include/clang/Driver/Types.h3
-rw-r--r--include/clang/Format/Format.h11
-rw-r--r--include/clang/Frontend/CodeGenOptions.def4
-rw-r--r--include/clang/Frontend/CodeGenOptions.h1
-rw-r--r--include/clang/Frontend/CompilerInstance.h21
-rw-r--r--include/clang/Lex/ModuleMap.h6
-rw-r--r--include/clang/Lex/Preprocessor.h16
-rw-r--r--include/clang/Parse/Parser.h56
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h2
-rw-r--r--include/clang/Sema/DeclSpec.h31
-rw-r--r--include/clang/Sema/Sema.h107
-rw-r--r--include/clang/Sema/Template.h1
-rw-r--r--include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--include/clang/Serialization/ASTReader.h66
-rw-r--r--include/clang/Serialization/ASTWriter.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerRegistry.h7
-rw-r--r--lib/AST/ASTContext.cpp504
-rw-r--r--lib/AST/ASTDiagnostic.cpp15
-rw-r--r--lib/AST/ASTDumper.cpp38
-rw-r--r--lib/AST/ASTImporter.cpp92
-rw-r--r--lib/AST/Decl.cpp16
-rw-r--r--lib/AST/DeclBase.cpp1
-rw-r--r--lib/AST/DeclCXX.cpp6
-rw-r--r--lib/AST/DeclObjC.cpp214
-rw-r--r--lib/AST/DeclPrinter.cpp58
-rw-r--r--lib/AST/Expr.cpp10
-rw-r--r--lib/AST/ItaniumMangle.cpp13
-rw-r--r--lib/AST/Type.cpp1034
-rw-r--r--lib/AST/TypeLoc.cpp69
-rw-r--r--lib/AST/TypePrinter.cpp82
-rw-r--r--lib/ASTMatchers/ASTMatchersInternal.cpp18
-rw-r--r--lib/ASTMatchers/Dynamic/Parser.cpp2
-rw-r--r--lib/ASTMatchers/Dynamic/VariantValue.cpp4
-rw-r--r--lib/Basic/FileManager.cpp3
-rw-r--r--lib/Basic/IdentifierTable.cpp4
-rw-r--r--lib/Basic/Module.cpp18
-rw-r--r--lib/Basic/Sanitizers.cpp25
-rw-r--r--lib/Basic/TargetInfo.cpp1
-rw-r--r--lib/Basic/Targets.cpp266
-rw-r--r--lib/CodeGen/BackendUtil.cpp3
-rw-r--r--lib/CodeGen/CGAtomic.cpp1
-rw-r--r--lib/CodeGen/CGBuiltin.cpp106
-rw-r--r--lib/CodeGen/CGCall.cpp100
-rw-r--r--lib/CodeGen/CGClass.cpp88
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp114
-rw-r--r--lib/CodeGen/CGDebugInfo.h305
-rw-r--r--lib/CodeGen/CGDecl.cpp3
-rw-r--r--lib/CodeGen/CGException.cpp358
-rw-r--r--lib/CodeGen/CGExpr.cpp22
-rw-r--r--lib/CodeGen/CGObjC.cpp36
-rw-r--r--lib/CodeGen/CGObjCRuntime.cpp4
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.cpp92
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.h9
-rw-r--r--lib/CodeGen/CGRecordLayout.h12
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.cpp12
-rw-r--r--lib/CodeGen/CGStmt.cpp26
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp3
-rw-r--r--lib/CodeGen/CGVTables.cpp25
-rw-r--r--lib/CodeGen/CMakeLists.txt2
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp16
-rw-r--r--lib/CodeGen/CodeGenFunction.h77
-rw-r--r--lib/CodeGen/CodeGenModule.cpp5
-rw-r--r--lib/CodeGen/CodeGenModule.h4
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp8
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp34
-rw-r--r--lib/CodeGen/ObjectFilePCHContainerOperations.cpp193
-rw-r--r--lib/CodeGen/TargetInfo.cpp10
-rw-r--r--lib/Driver/Action.cpp21
-rw-r--r--lib/Driver/Driver.cpp374
-rw-r--r--lib/Driver/Job.cpp12
-rw-r--r--lib/Driver/MSVCToolChain.cpp3
-rw-r--r--lib/Driver/MinGWToolChain.cpp60
-rw-r--r--lib/Driver/SanitizerArgs.cpp15
-rw-r--r--lib/Driver/ToolChain.cpp2
-rw-r--r--lib/Driver/ToolChains.cpp78
-rw-r--r--lib/Driver/ToolChains.h17
-rw-r--r--lib/Driver/Tools.cpp322
-rw-r--r--lib/Driver/Types.cpp21
-rw-r--r--lib/Format/ContinuationIndenter.cpp8
-rw-r--r--lib/Format/Format.cpp35
-rw-r--r--lib/Format/FormatToken.cpp14
-rw-r--r--lib/Format/FormatToken.h125
-rw-r--r--lib/Format/TokenAnnotator.cpp18
-rw-r--r--lib/Format/UnwrappedLineParser.cpp38
-rw-r--r--lib/Frontend/ASTUnit.cpp7
-rw-r--r--lib/Frontend/CompilerInstance.cpp27
-rw-r--r--lib/Frontend/CompilerInvocation.cpp6
-rw-r--r--lib/Frontend/CreateInvocationFromCommandLine.cpp21
-rw-r--r--lib/Frontend/PCHContainerOperations.cpp2
-rw-r--r--lib/Headers/Intrin.h154
-rw-r--r--lib/Headers/altivec.h1319
-rw-r--r--lib/Headers/avx512vlbwintrin.h1045
-rw-r--r--lib/Lex/HeaderSearch.cpp18
-rw-r--r--lib/Lex/ModuleMap.cpp11
-rw-r--r--lib/Lex/PPMacroExpansion.cpp3
-rw-r--r--lib/Parse/ParseDecl.cpp66
-rw-r--r--lib/Parse/ParseDeclCXX.cpp27
-rw-r--r--lib/Parse/ParseExprCXX.cpp7
-rw-r--r--lib/Parse/ParseInit.cpp36
-rw-r--r--lib/Parse/ParseObjc.cpp643
-rw-r--r--lib/Parse/ParseTemplate.cpp80
-rw-r--r--lib/Parse/ParseTentative.cpp3
-rw-r--r--lib/Parse/Parser.cpp55
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp6
-rw-r--r--lib/Sema/DeclSpec.cpp14
-rw-r--r--lib/Sema/SemaCast.cpp6
-rw-r--r--lib/Sema/SemaChecking.cpp102
-rw-r--r--lib/Sema/SemaCodeComplete.cpp137
-rw-r--r--lib/Sema/SemaDecl.cpp200
-rw-r--r--lib/Sema/SemaDeclAttr.cpp26
-rw-r--r--lib/Sema/SemaDeclObjC.cpp1004
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp2
-rw-r--r--lib/Sema/SemaExpr.cpp82
-rw-r--r--lib/Sema/SemaExprMember.cpp3
-rw-r--r--lib/Sema/SemaExprObjC.cpp123
-rw-r--r--lib/Sema/SemaObjCProperty.cpp8
-rw-r--r--lib/Sema/SemaOpenMP.cpp14
-rw-r--r--lib/Sema/SemaOverload.cpp18
-rw-r--r--lib/Sema/SemaPseudoObject.cpp36
-rw-r--r--lib/Sema/SemaStmt.cpp5
-rw-r--r--lib/Sema/SemaStmtAsm.cpp24
-rw-r--r--lib/Sema/SemaTemplate.cpp39
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp2
-rw-r--r--lib/Sema/SemaType.cpp576
-rw-r--r--lib/Sema/TreeTransform.h195
-rw-r--r--lib/Serialization/ASTCommon.cpp1
-rw-r--r--lib/Serialization/ASTReader.cpp155
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp102
-rw-r--r--lib/Serialization/ASTReaderInternals.h4
-rw-r--r--lib/Serialization/ASTWriter.cpp146
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp132
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/CheckerRegistry.cpp25
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp9
-rw-r--r--lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp1
-rw-r--r--test/ARCMT/check-with-pch.m1
-rw-r--r--test/ARCMT/migrate-on-pch-and-module.m2
-rw-r--r--test/ARCMT/objcmt-with-pch.m1
-rw-r--r--test/ARCMT/objcmt-with-pch.m.result1
-rw-r--r--test/Analysis/analyzer-checker-config.c12
-rw-r--r--test/Analysis/blocks.m48
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/CXX/class/class.mem/p13.cpp41
-rw-r--r--test/CXX/class/class.mem/p2.cpp7
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp6
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp2
-rw-r--r--test/CXX/drs/dr19xx.cpp15
-rw-r--r--test/CXX/drs/dr1xx.cpp4
-rw-r--r--test/CXX/drs/dr3xx.cpp12
-rw-r--r--test/CXX/expr/expr.const/p2-0x.cpp2
-rw-r--r--test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp1
-rw-r--r--test/CodeGen/align-systemz.c16
-rw-r--r--test/CodeGen/arm-long-calls.c7
-rw-r--r--test/CodeGen/arm64-abi-vector.c10
-rw-r--r--test/CodeGen/arm64-arguments.c68
-rw-r--r--test/CodeGen/arm64-be-bitfield.c2
-rw-r--r--test/CodeGen/asm-attrs.c33
-rw-r--r--test/CodeGen/atomic-ops.c1
-rw-r--r--test/CodeGen/attr-target.c3
-rw-r--r--test/CodeGen/available-externally-hidden.cpp32
-rw-r--r--test/CodeGen/available-externally-suppress.c10
-rw-r--r--test/CodeGen/avx512vlbw-builtins.c585
-rw-r--r--test/CodeGen/big-atomic-ops.c2
-rw-r--r--test/CodeGen/bitfield-2.c12
-rw-r--r--test/CodeGen/builtins-ppc-altivec.c88
-rw-r--r--test/CodeGen/builtins-ppc-p8vector.c663
-rw-r--r--test/CodeGen/builtins-ppc-vsx.c476
-rw-r--r--test/CodeGen/debug-info-block.c27
-rw-r--r--test/CodeGen/exceptions-seh-finally.c76
-rw-r--r--test/CodeGen/exceptions-seh-leave.c30
-rw-r--r--test/CodeGen/exceptions-seh.c139
-rw-r--r--test/CodeGen/inline.c4
-rw-r--r--test/CodeGen/packed-nest-unpacked.c31
-rw-r--r--test/CodeGen/ppc64-struct-onefloat.c16
-rw-r--r--test/CodeGen/ppc64le-aggregates.c18
-rw-r--r--test/CodeGenCXX/2012-03-16-StoreAlign.cpp2
-rw-r--r--test/CodeGenCXX/cfi-ms-rtti.cpp12
-rw-r--r--test/CodeGenCXX/cfi-vcall.cpp23
-rw-r--r--test/CodeGenCXX/debug-info-namespace.cpp3
-rw-r--r--test/CodeGenCXX/eh-aggregate-copy-destroy.cpp37
-rw-r--r--test/CodeGenCXX/eh-aggregated-inits-unwind.cpp47
-rw-r--r--test/CodeGenCXX/eh-aggregated-inits.cpp46
-rw-r--r--test/CodeGenCXX/exceptions-seh-filter-captures.cpp14
-rw-r--r--test/CodeGenCXX/exceptions-seh.cpp4
-rw-r--r--test/CodeGenCXX/pr24097.cpp20
-rw-r--r--test/CodeGenCXX/sanitize-dtor-callback.cpp17
-rw-r--r--test/CodeGenCXX/varargs.cpp2
-rw-r--r--test/CodeGenCXX/x86_64-arguments-avx.cpp9
-rw-r--r--test/CodeGenCXX/x86_64-arguments.cpp16
-rw-r--r--test/CodeGenObjC/parameterized_classes.m63
-rw-r--r--test/CodeGenObjCXX/mangle.mm15
-rw-r--r--test/Driver/apple-kext-mkernel.c2
-rw-r--r--test/Driver/arm-long-calls.c6
-rw-r--r--test/Driver/cl-eh.cpp14
-rw-r--r--test/Driver/clang_f_opts.c39
-rw-r--r--test/Driver/crash-report-modules.m2
-rw-r--r--test/Driver/crash-report.c6
-rw-r--r--test/Driver/cuda-options.cu111
-rw-r--r--test/Driver/fsanitize.c7
-rw-r--r--test/Driver/nacl-direct.c35
-rw-r--r--test/Driver/ppc-abi.c2
-rw-r--r--test/Driver/ppc-dependent-options.cpp62
-rw-r--r--test/Driver/ppc-endian.c9
-rw-r--r--test/Driver/ppc-features.cpp6
-rw-r--r--test/Frontend/ast-codegen.c1
-rw-r--r--test/Headers/xmmintrin.c2
-rw-r--r--test/Index/TestClassForwardDecl.m2
-rw-r--r--test/Index/annotate-parameterized-classes.m38
-rw-r--r--test/Index/annotate-tokens.m7
-rw-r--r--test/Index/attributes-cuda.cu22
-rw-r--r--test/Index/c-index-api-loadTU-test.m2
-rw-r--r--test/Index/c-index-getCursor-test.m1
-rw-r--r--test/Index/comment-objc-parameterized-classes.m19
-rw-r--r--test/Index/complete-blocks.m12
-rw-r--r--test/Index/complete-ctor-inits.cpp16
-rw-r--r--test/Index/complete-method-decls.m20
-rw-r--r--test/Index/complete-parameterized-classes.m79
-rw-r--r--test/Index/index-file.cu9
-rw-r--r--test/Index/pch-with-module.m1
-rw-r--r--test/Index/print-mangled-name.cpp1
-rw-r--r--test/Modules/Inputs/diagnostics-aux-2.modulemap3
-rw-r--r--test/Modules/Inputs/diagnostics-aux.modulemap2
-rw-r--r--test/Modules/Inputs/explicit-build-prefer-self/map4
-rw-r--r--test/Modules/Inputs/merge-template-pattern-visibility/a.h5
-rw-r--r--test/Modules/Inputs/merge-template-pattern-visibility/b.h9
-rw-r--r--test/Modules/Inputs/merge-template-pattern-visibility/module.modulemap4
-rw-r--r--test/Modules/Inputs/module.map11
-rw-r--r--test/Modules/Inputs/multiple-include/a.h1
-rw-r--r--test/Modules/Inputs/multiple-include/b.h3
-rw-r--r--test/Modules/Inputs/multiple-include/c.h4
-rw-r--r--test/Modules/Inputs/multiple-include/module.modulemap2
-rw-r--r--test/Modules/Inputs/multiple-include/x.h0
-rw-r--r--test/Modules/Inputs/namespaces-left.h2
-rw-r--r--test/Modules/Inputs/namespaces-right.h2
-rw-r--r--test/Modules/Inputs/namespaces-top.h2
-rw-r--r--test/Modules/Inputs/submodules-merge-defs/defs.h3
-rw-r--r--test/Modules/compiler_builtins_arm.m2
-rw-r--r--test/Modules/dependency-gen-inferred-map.m1
-rw-r--r--test/Modules/dependency-gen-pch.m1
-rw-r--r--test/Modules/diagnostics.modulemap3
-rw-r--r--test/Modules/irgen.c1
-rw-r--r--test/Modules/linkage-merge.m4
-rw-r--r--test/Modules/merge-target-features.cpp2
-rw-r--r--test/Modules/merge-template-pattern-visibility.cpp4
-rw-r--r--test/Modules/multiple-include.cpp5
-rw-r--r--test/Modules/pch_container.m17
-rw-r--r--test/Modules/requires.m4
-rw-r--r--test/Modules/self-import-header.m2
-rw-r--r--test/Modules/signal.m2
-rw-r--r--test/Modules/submodules-merge-defs.cpp5
-rw-r--r--test/Modules/templates-2.mm2
-rw-r--r--test/Modules/templates.mm2
-rw-r--r--test/Modules/va_list.m1
-rw-r--r--test/OpenMP/atomic_capture_codegen.cpp2
-rw-r--r--test/OpenMP/atomic_read_codegen.c2
-rw-r--r--test/OpenMP/atomic_update_codegen.cpp2
-rw-r--r--test/OpenMP/atomic_write_codegen.c2
-rw-r--r--test/OpenMP/barrier_codegen.cpp2
-rw-r--r--test/OpenMP/cancel_codegen.cpp95
-rw-r--r--test/OpenMP/cancellation_point_codegen.cpp2
-rw-r--r--test/OpenMP/critical_codegen.cpp2
-rw-r--r--test/OpenMP/flush_codegen.cpp2
-rw-r--r--test/OpenMP/for_codegen.cpp2
-rw-r--r--test/OpenMP/for_firstprivate_codegen.cpp9
-rw-r--r--test/OpenMP/for_lastprivate_codegen.cpp9
-rw-r--r--test/OpenMP/for_private_codegen.cpp9
-rw-r--r--test/OpenMP/for_reduction_codegen.cpp9
-rw-r--r--test/OpenMP/for_simd_codegen.cpp2
-rw-r--r--test/OpenMP/master_codegen.cpp2
-rw-r--r--test/OpenMP/ordered_codegen.cpp2
-rw-r--r--test/OpenMP/parallel_codegen.cpp2
-rw-r--r--test/OpenMP/parallel_copyin_codegen.cpp12
-rw-r--r--test/OpenMP/parallel_firstprivate_codegen.cpp8
-rw-r--r--test/OpenMP/parallel_for_codegen.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_codegen.cpp2
-rw-r--r--test/OpenMP/parallel_private_codegen.cpp10
-rw-r--r--test/OpenMP/parallel_reduction_codegen.cpp9
-rw-r--r--test/OpenMP/parallel_sections_codegen.cpp2
-rw-r--r--test/OpenMP/sections_codegen.cpp2
-rw-r--r--test/OpenMP/sections_firstprivate_codegen.cpp9
-rw-r--r--test/OpenMP/sections_lastprivate_codegen.cpp9
-rw-r--r--test/OpenMP/sections_private_codegen.cpp9
-rw-r--r--test/OpenMP/sections_reduction_codegen.cpp9
-rw-r--r--test/OpenMP/simd_codegen.cpp2
-rw-r--r--test/OpenMP/single_codegen.cpp12
-rw-r--r--test/OpenMP/single_firstprivate_codegen.cpp9
-rw-r--r--test/OpenMP/single_private_codegen.cpp9
-rw-r--r--test/OpenMP/task_codegen.cpp2
-rw-r--r--test/OpenMP/task_firstprivate_codegen.cpp10
-rw-r--r--test/OpenMP/task_if_codegen.cpp1
-rw-r--r--test/OpenMP/task_private_codegen.cpp10
-rw-r--r--test/OpenMP/taskgroup_codegen.cpp2
-rw-r--r--test/OpenMP/taskwait_codegen.cpp2
-rw-r--r--test/OpenMP/taskyield_codegen.cpp2
-rw-r--r--test/OpenMP/threadprivate_ast_print.cpp10
-rw-r--r--test/OpenMP/threadprivate_codegen.cpp288
-rw-r--r--test/OpenMP/threadprivate_messages.cpp1
-rw-r--r--test/PCH/__va_list_tag.c1
-rw-r--r--test/PCH/arc.m1
-rw-r--r--test/PCH/asm.c1
-rw-r--r--test/PCH/chain-external-defs.c1
-rw-r--r--test/PCH/chain-openmp-threadprivate.cpp19
-rw-r--r--test/PCH/chain-trivial.c1
-rw-r--r--test/PCH/cxx-ms-function-specialization-class-scope.cpp1
-rw-r--r--test/PCH/cxx1y-variable-templates.cpp4
-rw-r--r--test/PCH/external-defs.c1
-rw-r--r--test/PCH/floating-literal.c1
-rw-r--r--test/PCH/local_static.cpp1
-rw-r--r--test/PCH/objc_kindof.m33
-rw-r--r--test/PCH/objc_parameterized_classes.m45
-rw-r--r--test/PCH/pchpch.c1
-rw-r--r--test/PCH/reloc.c1
-rw-r--r--test/PCH/subscripting-literals.m1
-rw-r--r--test/PCH/target-options.c1
-rw-r--r--test/PCH/tentative-defs.c1
-rw-r--r--test/PCH/thread-local.cpp2
-rw-r--r--test/PCH/va_arg.c1
-rw-r--r--test/PCH/va_arg.cpp1
-rw-r--r--test/Parser/MicrosoftExtensions.c2
-rw-r--r--test/Parser/MicrosoftExtensions.cpp7
-rw-r--r--test/Parser/cxx-default-delete.cpp2
-rw-r--r--test/Parser/objc-error-qualified-implementation.m2
-rw-r--r--test/Parser/objcxx11-protocol-in-template.mm7
-rw-r--r--test/Parser/placeholder-recovery.m9
-rw-r--r--test/Profile/Inputs/gcc-flag-compatibility.proftext5
-rw-r--r--test/Profile/gcc-flag-compatibility.c43
-rw-r--r--test/Sema/array-declared-as-incorrect-type.c6
-rw-r--r--test/Sema/dllimport.c12
-rw-r--r--test/Sema/enable_if.c15
-rw-r--r--test/Sema/inline-asm-validate-tmpl.cpp25
-rw-r--r--test/Sema/mrtd.c8
-rw-r--r--test/Sema/shift.c5
-rw-r--r--test/Sema/struct-compat.c4
-rw-r--r--test/Sema/tls_alignment.cpp75
-rw-r--r--test/Sema/types.c2
-rw-r--r--test/Sema/var-redecl.c28
-rw-r--r--test/Sema/x86_64-linux-android.c2
-rw-r--r--test/SemaCXX/alias-template.cpp6
-rw-r--r--test/SemaCXX/array-bound-merge.cpp2
-rw-r--r--test/SemaCXX/cast-lvalue-to-rvalue-reference.cpp8
-rw-r--r--test/SemaCXX/constructor.cpp3
-rw-r--r--test/SemaCXX/cxx11-thread-local.cpp2
-rw-r--r--test/SemaCXX/cxx1y-generic-lambdas.cpp38
-rw-r--r--test/SemaCXX/cxx1y-variable-templates_in_class.cpp4
-rw-r--r--test/SemaCXX/cxx1y-variable-templates_top_level.cpp6
-rw-r--r--test/SemaCXX/dllimport.cpp12
-rw-r--r--test/SemaCXX/extern-c.cpp2
-rw-r--r--test/SemaCXX/lambda-expressions.cpp30
-rw-r--r--test/SemaCXX/lookup-member.cpp7
-rw-r--r--test/SemaCXX/struct-class-redecl.cpp4
-rw-r--r--test/SemaCXX/using-decl-1.cpp64
-rw-r--r--test/SemaObjC/block-type-safety.m8
-rw-r--r--test/SemaObjC/conditional-expr-8.m33
-rw-r--r--test/SemaObjC/conditional-expr.m11
-rw-r--r--test/SemaObjC/interface-1.m2
-rw-r--r--test/SemaObjC/kindof.m304
-rw-r--r--test/SemaObjC/objc2-merge-gc-attribue-decl.m16
-rw-r--r--test/SemaObjC/parameterized_classes.m357
-rw-r--r--test/SemaObjC/parameterized_classes_collection_literal.m52
-rw-r--r--test/SemaObjC/parameterized_classes_subst.m428
-rw-r--r--test/SemaObjC/protocol-archane.m4
-rw-r--r--test/SemaObjC/protocol-warn.m2
-rw-r--r--test/SemaObjCXX/Inputs/nullability-pragmas-generics-1.h21
-rw-r--r--test/SemaObjCXX/nullability-pragmas.mm12
-rw-r--r--test/SemaObjCXX/objc2-merge-gc-attribue-decl.mm16
-rw-r--r--test/SemaObjCXX/parameterized_classes.mm26
-rw-r--r--test/SemaObjCXX/parameterized_classes_subst.mm440
-rw-r--r--test/SemaTemplate/injected-class-name.cpp6
-rw-r--r--test/Tooling/ms-asm-no-target.cpp12
-rw-r--r--test/lit.cfg4
-rw-r--r--tools/c-arcmt-test/Makefile11
-rw-r--r--tools/c-index-test/Makefile11
-rw-r--r--tools/clang-check/CMakeLists.txt4
-rw-r--r--tools/clang-check/ClangCheck.cpp12
-rw-r--r--tools/clang-check/Makefile9
-rw-r--r--tools/clang-format/clang-format.py18
-rw-r--r--tools/driver/CMakeLists.txt7
-rw-r--r--tools/driver/cc1_main.cpp6
-rw-r--r--tools/libclang/BuildSystem.cpp4
-rw-r--r--tools/libclang/CIndex.cpp67
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp2
-rw-r--r--tools/libclang/CMakeLists.txt2
-rw-r--r--tools/libclang/CXCursor.cpp12
-rw-r--r--tools/libclang/CursorVisitor.h2
-rw-r--r--tools/libclang/Makefile8
-rw-r--r--tools/libclang/libclang.exports1
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.h1
-rw-r--r--unittests/ASTMatchers/Dynamic/Makefile4
-rw-r--r--unittests/ASTMatchers/Dynamic/ParserTest.cpp2
-rw-r--r--unittests/ASTMatchers/Dynamic/RegistryTest.cpp44
-rw-r--r--unittests/ASTMatchers/Dynamic/VariantValueTest.cpp6
-rw-r--r--unittests/CMakeLists.txt3
-rw-r--r--unittests/Format/FormatTest.cpp87
-rw-r--r--unittests/Format/FormatTestJS.cpp11
-rw-r--r--unittests/Frontend/CMakeLists.txt1
-rw-r--r--unittests/libclang/LibclangTest.cpp4
-rw-r--r--unittests/libclang/Makefile11
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp4
-rwxr-xr-xutils/analyzer/CmpRuns.py6
-rw-r--r--utils/analyzer/SATestBuild.py15
-rw-r--r--www/cxx_dr_status.html6
440 files changed, 17512 insertions, 3076 deletions
diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst
index ab7bd872ca28..031daeeaa123 100644
--- a/docs/ClangFormatStyleOptions.rst
+++ b/docs/ClangFormatStyleOptions.rst
@@ -275,6 +275,9 @@ the configuration (without a prefix: ``Auto``).
* ``BS_Linux`` (in configuration: ``Linux``)
Like ``Attach``, but break before braces on function, namespace and
class definitions.
+ * ``BS_Mozilla`` (in configuration: ``Mozilla``)
+ Like ``Attach``, but break before braces on enum, function, and record
+ definitions.
* ``BS_Stroustrup`` (in configuration: ``Stroustrup``)
Like ``Attach``, but break before function definitions, and 'else'.
* ``BS_Allman`` (in configuration: ``Allman``)
@@ -394,6 +397,12 @@ the configuration (without a prefix: ``Auto``).
(https://developers.google.com/protocol-buffers/).
+**MacroBlockBegin** (``std::string``)
+ A regular expression matching macros that start a block.
+
+**MacroBlockEnd** (``std::string``)
+ A regular expression matching macros that end a block.
+
**MaxEmptyLinesToKeep** (``unsigned``)
The maximum number of consecutive empty lines to keep.
diff --git a/docs/CrossCompilation.rst b/docs/CrossCompilation.rst
index d3a775b4fd44..8a8027117372 100644
--- a/docs/CrossCompilation.rst
+++ b/docs/CrossCompilation.rst
@@ -92,7 +92,7 @@ will be assumed, which sets the defaults for the specified architecture.
The system name is generally the OS (linux, darwin), but could be special
like the bare-metal "none".
-When a parameter is not important, they can be omitted, or you can
+When a parameter is not important, it can be omitted, or you can
choose ``unknown`` and the defaults will be used. If you choose a parameter
that Clang doesn't know, like ``blerg``, it'll ignore and assume
``unknown``, which is not always desired, so be careful.
diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst
index 0b4775ba6ad4..6a4dd5ccbf3c 100644
--- a/docs/LanguageExtensions.rst
+++ b/docs/LanguageExtensions.rst
@@ -1991,10 +1991,10 @@ compile time. Partial unrolling replicates the loop body within the loop and
reduces the trip count.
If ``unroll(full)`` is specified the unroller will attempt to fully unroll the
-loop if the trip count is known at compile time. If the loop count is not known
-or the fully unrolled code size is greater than the limit specified by the
-`-pragma-unroll-threshold` command line option the loop will be partially
-unrolled subject to the same limit.
+loop if the trip count is known at compile time. If the fully unrolled code size
+is greater than an internal limit the loop will be partially unrolled up to this
+limit. If the loop count is not known at compile time the loop will not be
+unrolled.
.. code-block:: c++
@@ -2006,7 +2006,7 @@ unrolled subject to the same limit.
The unroll count can be specified explicitly with ``unroll_count(_value_)`` where
_value_ is a positive integer. If this value is greater than the trip count the
loop will be fully unrolled. Otherwise the loop is partially unrolled subject
-to the `-pragma-unroll-threshold` limit.
+to the same code size limit as with ``unroll(full)``.
.. code-block:: c++
diff --git a/docs/PCHInternals.rst b/docs/PCHInternals.rst
index a36e65c199c6..8f66ddf0e1d8 100644
--- a/docs/PCHInternals.rst
+++ b/docs/PCHInternals.rst
@@ -124,20 +124,30 @@ section <pchinternals-chained>`.
AST File Contents
-----------------
-Clang's AST files are organized into several different blocks, each of which
-contains the serialized representation of a part of Clang's internal
+An AST file produced by clang is an object file container with a ``clangast``
+(COFF) or ``__clangast`` (ELF and Mach-O) section containing the serialized AST.
+Other target-specific sections in the object file container are used to hold
+debug information for the data types defined in the AST. Tools built on top of
+libclang that do not need debug information may also produce raw AST files that
+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>`_.
The contents of each of these logical blocks are described below.
.. image:: PCHLayout.png
-For a given AST file, the `llvm-bcanalyzer
-<http://llvm.org/docs/CommandGuide/llvm-bcanalyzer.html>`_ utility can be used
-to examine the actual structure of the bitstream for the AST file. This
-information can be used both to help understand the structure of the AST file
-and to isolate areas where AST files can still be optimized, e.g., through the
-introduction of abbreviations.
+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>`_
+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
+optimized, e.g., through the introduction of abbreviations.
+
Metadata Block
^^^^^^^^^^^^^^
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index cd1b2b3c341d..20ee5696e06a 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -1488,6 +1488,45 @@ instrumentation:
profile. As you make changes to your code, clang may no longer be able to
use the profile data. It will warn you when this happens.
+Profile generation and use can also be controlled by the GCC-compatible flags
+``-fprofile-generate`` and ``-fprofile-use``. Although these flags are
+semantically equivalent to their GCC counterparts, they *do not* handle
+GCC-compatible profiles. They are only meant to implement GCC's semantics
+with respect to profile creation and use.
+
+.. option:: -fprofile-generate[=<dirname>]
+
+ Without any other arguments, ``-fprofile-generate`` behaves identically to
+ ``-fprofile-instr-generate``. When given a directory name, it generates the
+ profile file ``default.profraw`` in the directory named ``dirname``. If
+ ``dirname`` does not exist, it will be created at runtime. The environment
+ variable ``LLVM_PROFILE_FILE`` can be used to override the directory and
+ filename for the profile file at runtime. For example,
+
+ .. code-block:: console
+
+ $ clang++ -O2 -fprofile-generate=yyy/zzz code.cc -o code
+
+ When ``code`` is executed, the profile will be written to the file
+ ``yyy/zzz/default.profraw``. This can be altered at runtime via the
+ ``LLVM_PROFILE_FILE`` environment variable:
+
+ .. code-block:: console
+
+ $ LLVM_PROFILE_FILE=/tmp/myprofile/code.profraw ./code
+
+ The above invocation will produce the profile file
+ ``/tmp/myprofile/code.profraw`` instead of ``yyy/zzz/default.profraw``.
+ Notice that ``LLVM_PROFILE_FILE`` overrides the directory *and* the file
+ name for the profile file.
+
+.. option:: -fprofile-use[=<pathname>]
+
+ Without any other arguments, ``-fprofile-use`` behaves identically to
+ ``-fprofile-instr-use``. Otherwise, if ``pathname`` is the full path to a
+ profile file, it reads from that file. If ``pathname`` is a directory name,
+ it reads from ``pathname/default.profdata``.
+
Controlling Size of Debug Information
-------------------------------------
diff --git a/include/clang-c/BuildSystem.h b/include/clang-c/BuildSystem.h
index 7aa01914cf24..8d323a4e6cae 100644
--- a/include/clang-c/BuildSystem.h
+++ b/include/clang-c/BuildSystem.h
@@ -73,7 +73,7 @@ clang_VirtualFileOverlay_setCaseSensitivity(CXVirtualFileOverlay,
*
* \param options is reserved, always pass 0.
* \param out_buffer_ptr pointer to receive the buffer pointer, which should be
- * disposed using \c free().
+ * disposed using \c clang_free().
* \param out_buffer_size pointer to receive the buffer size.
* \returns 0 for success, non-zero to indicate an error.
*/
@@ -83,6 +83,14 @@ clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay, unsigned options,
unsigned *out_buffer_size);
/**
+ * \brief free memory allocated by libclang, such as the buffer returned by
+ * \c CXVirtualFileOverlay() or \c clang_ModuleMapDescriptor_writeToBuffer().
+ *
+ * \param buffer memory pointer to free.
+ */
+CINDEX_LINKAGE void clang_free(void *buffer);
+
+/**
* \brief Dispose a \c CXVirtualFileOverlay object.
*/
CINDEX_LINKAGE void clang_VirtualFileOverlay_dispose(CXVirtualFileOverlay);
@@ -122,7 +130,7 @@ clang_ModuleMapDescriptor_setUmbrellaHeader(CXModuleMapDescriptor,
*
* \param options is reserved, always pass 0.
* \param out_buffer_ptr pointer to receive the buffer pointer, which should be
- * disposed using \c free().
+ * disposed using \c clang_free().
* \param out_buffer_size pointer to receive the buffer size.
* \returns 0 for success, non-zero to indicate an error.
*/
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 682be3d41513..a2bd55a089ed 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -236,6 +236,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType ObjCClassRedefinitionType;
QualType ObjCSelRedefinitionType;
+ /// The identifier 'NSObject'.
+ IdentifierInfo *NSObjectName = nullptr;
+
+ /// The identifier 'NSCopying'.
+ IdentifierInfo *NSCopyingName = nullptr;
+
QualType ObjCConstantStringType;
mutable RecordDecl *CFConstantStringTypeDecl;
@@ -1189,9 +1195,15 @@ public:
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
ObjCInterfaceDecl *PrevDecl = nullptr) const;
+ /// Legacy interface: cannot provide type arguments or __kindof.
QualType getObjCObjectType(QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) const;
+
+ QualType getObjCObjectType(QualType Base,
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf) const;
bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
/// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in
@@ -1351,6 +1363,24 @@ public:
ObjCSelRedefinitionType = RedefType;
}
+ /// Retrieve the identifier 'NSObject'.
+ IdentifierInfo *getNSObjectName() {
+ if (!NSObjectName) {
+ NSObjectName = &Idents.get("NSObject");
+ }
+
+ return NSObjectName;
+ }
+
+ /// Retrieve the identifier 'NSCopying'.
+ IdentifierInfo *getNSCopyingName() {
+ if (!NSCopyingName) {
+ NSCopyingName = &Idents.get("NSCopying");
+ }
+
+ return NSCopyingName;
+ }
+
/// \brief Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
QualType getObjCInstanceType() {
diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
index 923d98fb1664..dd167fe27c02 100644
--- a/include/clang/AST/DataRecursiveASTVisitor.h
+++ b/include/clang/AST/DataRecursiveASTVisitor.h
@@ -940,6 +940,9 @@ DEF_TRAVERSE_TYPE(ObjCObjectType, {
// type is itself.
if (T->getBaseType().getTypePtr() != T)
TRY_TO(TraverseType(T->getBaseType()));
+ for (auto typeArg : T->getTypeArgsAsWritten()) {
+ TRY_TO(TraverseType(typeArg));
+ }
})
DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
@@ -1166,6 +1169,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
// type is itself.
if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
+ for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
+ TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
})
DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
@@ -1307,7 +1312,13 @@ DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
- })
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+ return true;
+})
DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
})
@@ -1316,7 +1327,16 @@ DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
- })
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+
+ if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
+ TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
+ }
+})
DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
})
@@ -1335,6 +1355,15 @@ DEF_TRAVERSE_DECL(ObjCMethodDecl, {
return true;
})
+DEF_TRAVERSE_DECL(ObjCTypeParamDecl, {
+ if (D->hasExplicitBound()) {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type alias, not something that was written in the
+ // source.
+ }
+})
+
DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
if (D->getTypeSourceInfo())
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index c3fb57770245..c42764b6f3bf 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -332,10 +332,14 @@ public:
SourceRange getReturnTypeSourceRange() const;
/// \brief Determine the type of an expression that sends a message to this
- /// function.
- QualType getSendResultType() const {
- return getReturnType().getNonLValueExprType(getASTContext());
- }
+ /// function. This replaces the type parameters with the types they would
+ /// get if the receiver was parameterless (e.g. it may replace the type
+ /// parameter with 'id').
+ QualType getSendResultType() const;
+
+ /// Determine the type of an expression that sends a message to this
+ /// function with the given receiver type.
+ QualType getSendResultType(QualType receiverType) const;
TypeSourceInfo *getReturnTypeSourceInfo() const { return ReturnTInfo; }
void setReturnTypeSourceInfo(TypeSourceInfo *TInfo) { ReturnTInfo = TInfo; }
@@ -399,6 +403,11 @@ public:
/// have already been created.
void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
+ /// \return the type for \c self and set \arg selfIsPseudoStrong and
+ /// \arg selfIsConsumed accordingly.
+ QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID,
+ bool &selfIsPseudoStrong, bool &selfIsConsumed);
+
ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
@@ -501,6 +510,183 @@ public:
friend class ASTDeclWriter;
};
+/// Describes the variance of a given generic parameter.
+enum class ObjCTypeParamVariance : uint8_t {
+ /// The parameter is invariant: must match exactly.
+ Invariant,
+ /// The parameter is covariant, e.g., X<T> is a subtype of X<U> when
+ /// the type parameter is covariant and T is a subtype of U.
+ Covariant,
+ /// The parameter is contravariant, e.g., X<T> is a subtype of X<U>
+ /// when the type parameter is covariant and U is a subtype of T.
+ Contravariant,
+};
+
+/// Represents the declaration of an Objective-C type parameter.
+///
+/// \code
+/// @interface NSDictionary<Key : id<NSCopying>, Value>
+/// @end
+/// \endcode
+///
+/// In the example above, both \c Key and \c Value are represented by
+/// \c ObjCTypeParamDecl. \c Key has an explicit bound of \c id<NSCopying>,
+/// while \c Value gets an implicit bound of \c id.
+///
+/// Objective-C type parameters are typedef-names in the grammar,
+class ObjCTypeParamDecl : public TypedefNameDecl {
+ void anchor() override;
+
+ /// Index of this type parameter in the type parameter list.
+ unsigned Index : 14;
+
+ /// The variance of the type parameter.
+ unsigned Variance : 2;
+
+ /// The location of the variance, if any.
+ SourceLocation VarianceLoc;
+
+ /// The location of the ':', which will be valid when the bound was
+ /// explicitly specified.
+ SourceLocation ColonLoc;
+
+ ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc,
+ ObjCTypeParamVariance variance, SourceLocation varianceLoc,
+ unsigned index,
+ SourceLocation nameLoc, IdentifierInfo *name,
+ SourceLocation colonLoc, TypeSourceInfo *boundInfo)
+ : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name,
+ boundInfo),
+ Index(index), Variance(static_cast<unsigned>(variance)),
+ VarianceLoc(varianceLoc), ColonLoc(colonLoc) { }
+
+public:
+ static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc,
+ ObjCTypeParamVariance variance,
+ SourceLocation varianceLoc,
+ unsigned index,
+ SourceLocation nameLoc,
+ IdentifierInfo *name,
+ SourceLocation colonLoc,
+ TypeSourceInfo *boundInfo);
+ static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ /// Determine the variance of this type parameter.
+ ObjCTypeParamVariance getVariance() const {
+ return static_cast<ObjCTypeParamVariance>(Variance);
+ }
+
+ /// Set the variance of this type parameter.
+ void setVariance(ObjCTypeParamVariance variance) {
+ Variance = static_cast<unsigned>(variance);
+ }
+
+ /// Retrieve the location of the variance keyword.
+ SourceLocation getVarianceLoc() const { return VarianceLoc; }
+
+ /// Retrieve the index into its type parameter list.
+ unsigned getIndex() const { return Index; }
+
+ /// Whether this type parameter has an explicitly-written type bound, e.g.,
+ /// "T : NSView".
+ bool hasExplicitBound() const { return ColonLoc.isValid(); }
+
+ /// Retrieve the location of the ':' separating the type parameter name
+ /// from the explicitly-specified bound.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ObjCTypeParam; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Stores a list of Objective-C type parameters for a parameterized class
+/// or a category/extension thereof.
+///
+/// \code
+/// @interface NSArray<T> // stores the <T>
+/// @end
+/// \endcode
+class ObjCTypeParamList {
+ /// Stores the components of a SourceRange as a POD.
+ struct PODSourceRange {
+ unsigned Begin;
+ unsigned End;
+ };
+
+ union {
+ /// Location of the left and right angle brackets.
+ PODSourceRange Brackets;
+
+ // Used only for alignment.
+ ObjCTypeParamDecl *AlignmentHack;
+ };
+
+ /// The number of parameters in the list, which are tail-allocated.
+ unsigned NumParams;
+
+ ObjCTypeParamList(SourceLocation lAngleLoc,
+ ArrayRef<ObjCTypeParamDecl *> typeParams,
+ SourceLocation rAngleLoc);
+
+public:
+ /// Create a new Objective-C type parameter list.
+ static ObjCTypeParamList *create(ASTContext &ctx,
+ SourceLocation lAngleLoc,
+ ArrayRef<ObjCTypeParamDecl *> typeParams,
+ SourceLocation rAngleLoc);
+
+ /// Iterate through the type parameters in the list.
+ typedef ObjCTypeParamDecl **iterator;
+
+ iterator begin() { return reinterpret_cast<ObjCTypeParamDecl **>(this + 1); }
+
+ iterator end() { return begin() + size(); }
+
+ /// Determine the number of type parameters in this list.
+ unsigned size() const { return NumParams; }
+
+ // Iterate through the type parameters in the list.
+ typedef ObjCTypeParamDecl * const *const_iterator;
+
+ const_iterator begin() const {
+ return reinterpret_cast<ObjCTypeParamDecl * const *>(this + 1);
+ }
+
+ const_iterator end() const {
+ return begin() + size();
+ }
+
+ ObjCTypeParamDecl *front() const {
+ assert(size() > 0 && "empty Objective-C type parameter list");
+ return *begin();
+ }
+
+ ObjCTypeParamDecl *back() const {
+ assert(size() > 0 && "empty Objective-C type parameter list");
+ return *(end() - 1);
+ }
+
+ SourceLocation getLAngleLoc() const {
+ return SourceLocation::getFromRawEncoding(Brackets.Begin);
+ }
+ SourceLocation getRAngleLoc() const {
+ return SourceLocation::getFromRawEncoding(Brackets.End);
+ }
+ SourceRange getSourceRange() const {
+ return SourceRange(getLAngleLoc(), getRAngleLoc());
+ }
+
+ /// Gather the default set of type arguments to be substituted for
+ /// these type parameters when dealing with an unspecialized type.
+ void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
+};
+
/// ObjCContainerDecl - Represents a container for method declarations.
/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
/// ObjCProtocolDecl, and ObjCImplDecl.
@@ -676,9 +862,9 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// declaration.
ObjCInterfaceDecl *Definition;
- /// Class's super class.
- ObjCInterfaceDecl *SuperClass;
-
+ /// When non-null, this is always an ObjCObjectType.
+ TypeSourceInfo *SuperClassTInfo;
+
/// Protocols referenced in the \@interface declaration
ObjCProtocolList ReferencedProtocols;
@@ -719,16 +905,13 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
};
/// One of the \c InheritedDesignatedInitializersState enumeratos.
mutable unsigned InheritedDesignatedInitializers : 2;
-
- /// \brief The location of the superclass, if any.
- SourceLocation SuperClassLoc;
/// \brief The location of the last location in this declaration, before
/// the properties/methods. For example, this will be the '>', '}', or
/// identifier,
SourceLocation EndLoc;
- DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(),
+ DefinitionData() : Definition(), SuperClassTInfo(), CategoryList(), IvarList(),
ExternallyCompleted(),
IvarListMissingImplementation(true),
HasDesignatedInitializers(),
@@ -736,11 +919,15 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
};
ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
- IdentifierInfo *Id, SourceLocation CLoc,
- ObjCInterfaceDecl *PrevDecl, bool IsInternal);
+ IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
+ SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
+ bool IsInternal);
void LoadExternalDefinition() const;
+ /// The type parameters associated with this class, if any.
+ ObjCTypeParamList *TypeParamList;
+
/// \brief Contains a pointer to the data associated with this class,
/// which will be NULL if this class has not yet been defined.
///
@@ -771,12 +958,33 @@ public:
static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
+ ObjCTypeParamList *typeParamList,
ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc = SourceLocation(),
bool isInternal = false);
static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
+ /// Retrieve the type parameters of this class.
+ ///
+ /// This function looks for a type parameter list for the given
+ /// class; if the class has been declared (with \c \@class) but not
+ /// defined (with \c \@interface), it will search for a declaration that
+ /// has type parameters, skipping any declarations that do not.
+ ObjCTypeParamList *getTypeParamList() const;
+
+ /// Set the type parameters of this class.
+ ///
+ /// This function is used by the AST importer, which must import the type
+ /// parameters after creating their DeclContext to avoid loops.
+ void setTypeParamList(ObjCTypeParamList *TPL);
+
+ /// Retrieve the type parameters written on this particular declaration of
+ /// the class.
+ ObjCTypeParamList *getTypeParamListAsWritten() const {
+ return TypeParamList;
+ }
+
SourceRange getSourceRange() const override LLVM_READONLY {
if (isThisDeclarationADefinition())
return ObjCContainerDecl::getSourceRange();
@@ -1023,7 +1231,16 @@ public:
/// a forward declaration (\@class) to a definition (\@interface).
void startDefinition();
- ObjCInterfaceDecl *getSuperClass() const {
+ /// Retrieve the superclass type.
+ const ObjCObjectType *getSuperClassType() const {
+ if (TypeSourceInfo *TInfo = getSuperClassTInfo())
+ return TInfo->getType()->castAs<ObjCObjectType>();
+
+ return nullptr;
+ }
+
+ // Retrieve the type source information for the superclass.
+ TypeSourceInfo *getSuperClassTInfo() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return nullptr;
@@ -1031,13 +1248,15 @@ public:
if (data().ExternallyCompleted)
LoadExternalDefinition();
- return data().SuperClass;
+ return data().SuperClassTInfo;
}
- void setSuperClass(ObjCInterfaceDecl * superCls) {
- data().SuperClass =
- (superCls && superCls->hasDefinition()) ? superCls->getDefinition()
- : superCls;
+ // Retrieve the declaration for the superclass of this class, which
+ // does not include any type arguments that apply to the superclass.
+ ObjCInterfaceDecl *getSuperClass() const;
+
+ void setSuperClass(TypeSourceInfo *superClass) {
+ data().SuperClassTInfo = superClass;
}
/// \brief Iterator that walks over the list of categories, filtering out
@@ -1329,8 +1548,8 @@ public:
void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }
- void setSuperClassLoc(SourceLocation Loc) { data().SuperClassLoc = Loc; }
- SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; }
+ /// Retrieve the starting location of the superclass.
+ SourceLocation getSuperClassLoc() const;
/// isImplicitInterfaceDecl - check that this is an implicitly declared
/// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
@@ -1438,6 +1657,10 @@ public:
void setSynthesize(bool synth) { Synthesized = synth; }
bool getSynthesize() const { return Synthesized; }
+ /// Retrieve the type of this instance variable when viewed as a member of a
+ /// specific object type.
+ QualType getUsageType(QualType objectType) const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCIvar; }
@@ -1719,6 +1942,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// Interface belonging to this category
ObjCInterfaceDecl *ClassInterface;
+ /// The type parameters associated with this category, if any.
+ ObjCTypeParamList *TypeParamList;
+
/// referenced protocols in this category.
ObjCProtocolList ReferencedProtocols;
@@ -1736,13 +1962,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
+ ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc=SourceLocation(),
- SourceLocation IvarRBraceLoc=SourceLocation())
- : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
- ClassInterface(IDecl), NextClassCategory(nullptr),
- CategoryNameLoc(CategoryNameLoc),
- IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
- }
+ SourceLocation IvarRBraceLoc=SourceLocation());
public:
@@ -1752,6 +1974,7 @@ public:
SourceLocation CategoryNameLoc,
IdentifierInfo *Id,
ObjCInterfaceDecl *IDecl,
+ ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation());
static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -1759,6 +1982,17 @@ public:
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
+ /// Retrieve the type parameter list associated with this category or
+ /// extension.
+ ObjCTypeParamList *getTypeParamList() const { return TypeParamList; }
+
+ /// Set the type parameters of this category.
+ ///
+ /// This function is used by the AST importer, which must import the type
+ /// parameters after creating their DeclContext to avoid loops.
+ void setTypeParamList(ObjCTypeParamList *TPL);
+
+
ObjCCategoryImplDecl *getImplementation() const;
void setImplementation(ObjCCategoryImplDecl *ImplD);
@@ -2275,6 +2509,10 @@ public:
DeclTypeSourceInfo = TSI;
}
+ /// Retrieve the type when this property is used with a specific base object
+ /// type.
+ QualType getUsageType(QualType objectType) const;
+
PropertyAttributeKind getPropertyAttributes() const {
return PropertyAttributeKind(PropertyAttributes);
}
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 899e6487f737..f28e5196c7a4 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -687,40 +687,7 @@ public:
QualType getSuperReceiverType() const {
return QualType(Receiver.get<const Type*>(), 0);
}
- QualType getGetterResultType() const {
- QualType ResultType;
- if (isExplicitProperty()) {
- const ObjCPropertyDecl *PDecl = getExplicitProperty();
- if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl())
- ResultType = Getter->getReturnType();
- else
- ResultType = PDecl->getType();
- } else {
- const ObjCMethodDecl *Getter = getImplicitPropertyGetter();
- if (Getter)
- ResultType = Getter->getReturnType(); // with reference!
- }
- return ResultType;
- }
-
- QualType getSetterArgType() const {
- QualType ArgType;
- if (isImplicitProperty()) {
- const ObjCMethodDecl *Setter = getImplicitPropertySetter();
- ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
- ArgType = (*P)->getType();
- } else {
- if (ObjCPropertyDecl *PDecl = getExplicitProperty())
- if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) {
- ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
- ArgType = (*P)->getType();
- }
- if (ArgType.isNull())
- ArgType = getType();
- }
- return ArgType;
- }
-
+
ObjCInterfaceDecl *getClassReceiver() const {
return Receiver.get<ObjCInterfaceDecl*>();
}
@@ -728,6 +695,9 @@ public:
bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
+ /// 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();
}
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index b118503b674b..1017656b662c 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1008,6 +1008,9 @@ DEF_TRAVERSE_TYPE(ObjCObjectType, {
// type is itself.
if (T->getBaseType().getTypePtr() != T)
TRY_TO(TraverseType(T->getBaseType()));
+ for (auto typeArg : T->getTypeArgsAsWritten()) {
+ TRY_TO(TraverseType(typeArg));
+ }
})
DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
@@ -1234,6 +1237,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
// type is itself.
if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
+ for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
+ TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
})
DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
@@ -1382,7 +1387,12 @@ DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
- })
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+})
DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
})
@@ -1391,7 +1401,16 @@ DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
- })
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+
+ if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
+ TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
+ }
+})
DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
})
@@ -1410,6 +1429,15 @@ DEF_TRAVERSE_DECL(ObjCMethodDecl, {
return true;
})
+DEF_TRAVERSE_DECL(ObjCTypeParamDecl, {
+ if (D->hasExplicitBound()) {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type alias, not something that was written in the
+ // source.
+ }
+})
+
DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
if (D->getTypeSourceInfo())
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 97f13313b339..632d4b95e376 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -533,6 +533,24 @@ struct SplitQualType {
}
};
+/// The kind of type we are substituting Objective-C type arguments into.
+///
+/// The kind of substitution affects the replacement of type parameters when
+/// no concrete type information is provided, e.g., when dealing with an
+/// unspecialized type.
+enum class ObjCSubstitutionContext {
+ /// An ordinary type.
+ Ordinary,
+ /// The result type of a method or function.
+ Result,
+ /// The parameter type of a method or function.
+ Parameter,
+ /// The type of a property.
+ Property,
+ /// The superclass of a type.
+ Superclass,
+};
+
/// QualType - For efficiency, we don't store CV-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
/// greatly reduces the number of nodes we need to allocate for types (for
@@ -994,6 +1012,51 @@ public:
/// type other than void.
bool isCForbiddenLValueType() const;
+ /// Substitute type arguments for the Objective-C type parameters used in the
+ /// subject type.
+ ///
+ /// \param ctx ASTContext in which the type exists.
+ ///
+ /// \param typeArgs The type arguments that will be substituted for the
+ /// Objective-C type parameters in the subject type, which are generally
+ /// computed via \c Type::getObjCSubstitutions. If empty, the type
+ /// parameters will be replaced with their bounds or id/Class, as appropriate
+ /// for the context.
+ ///
+ /// \param context The context in which the subject type was written.
+ ///
+ /// \returns the resulting type.
+ QualType substObjCTypeArgs(ASTContext &ctx,
+ ArrayRef<QualType> typeArgs,
+ ObjCSubstitutionContext context) const;
+
+ /// Substitute type arguments from an object type for the Objective-C type
+ /// parameters used in the subject type.
+ ///
+ /// This operation combines the computation of type arguments for
+ /// substitution (\c Type::getObjCSubstitutions) with the actual process of
+ /// substitution (\c QualType::substObjCTypeArgs) for the convenience of
+ /// callers that need to perform a single substitution in isolation.
+ ///
+ /// \param objectType The type of the object whose member type we're
+ /// substituting into. For example, this might be the receiver of a message
+ /// or the base of a property access.
+ ///
+ /// \param dc The declaration context from which the subject type was
+ /// retrieved, which indicates (for example) which type parameters should
+ /// be substituted.
+ ///
+ /// \param context The context in which the subject type was written.
+ ///
+ /// \returns the subject type after replacing all of the Objective-C type
+ /// parameters with their corresponding arguments.
+ QualType substObjCMemberType(QualType objectType,
+ const DeclContext *dc,
+ ObjCSubstitutionContext context) const;
+
+ /// Strip Objective-C "__kindof" types from the given type.
+ QualType stripObjCKindOfType(const ASTContext &ctx) const;
+
private:
// These methods are implemented in a separate translation unit;
// "static"-ize them to avoid creating temporary QualTypes in the
@@ -1288,10 +1351,17 @@ protected:
unsigned : NumTypeBits;
+ /// The number of type arguments stored directly on this object type.
+ unsigned NumTypeArgs : 7;
+
/// NumProtocols - The number of protocols stored directly on this
/// object type.
- unsigned NumProtocols : 32 - NumTypeBits;
+ unsigned NumProtocols : 6;
+
+ /// Whether this is a "kindof" type.
+ unsigned IsKindOf : 1;
};
+ static_assert(NumTypeBits + 7 + 6 + 1 <= 32, "Does not fit in an unsigned");
class ReferenceTypeBitfields {
friend class ReferenceType;
@@ -1585,7 +1655,28 @@ public:
bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id
+
+ /// Whether the type is Objective-C 'id' or a __kindof type of an
+ /// object type, e.g., __kindof NSView * or __kindof id
+ /// <NSCopying>.
+ ///
+ /// \param bound Will be set to the bound on non-id subtype types,
+ /// which will be (possibly specialized) Objective-C class type, or
+ /// null for 'id.
+ bool isObjCIdOrObjectKindOfType(const ASTContext &ctx,
+ const ObjCObjectType *&bound) const;
+
bool isObjCClassType() const; // Class
+
+ /// Whether the type is Objective-C 'Class' or a __kindof type of an
+ /// Class type, e.g., __kindof Class <NSCopying>.
+ ///
+ /// Unlike \c isObjCIdOrObjectKindOfType, there is no relevant bound
+ /// here because Objective-C's type system cannot express "a class
+ /// object for a subclass of NSFoo".
+ bool isObjCClassOrClassKindOfType() const;
+
+ bool isBlockCompatibleObjCPointerType(ASTContext &ctx) const;
bool isObjCSelType() const; // Class
bool isObjCBuiltinType() const; // 'id' or 'Class'
bool isObjCARCBridgableType() const;
@@ -1697,6 +1788,7 @@ public:
/// NOTE: getAs*ArrayType are methods on ASTContext.
const RecordType *getAsUnionType() const;
const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
+ const ObjCObjectType *getAsObjCInterfaceType() const;
// The following is a convenience method that returns an ObjCObjectPointerType
// for object declared using an interface.
const ObjCObjectPointerType *getAsObjCInterfacePointerType() const;
@@ -1832,6 +1924,28 @@ public:
/// pointer type.
bool canHaveNullability() const;
+ /// Retrieve the set of substitutions required when accessing a member
+ /// of the Objective-C receiver type that is declared in the given context.
+ ///
+ /// \c *this is the type of the object we're operating on, e.g., the
+ /// receiver for a message send or the base of a property access, and is
+ /// expected to be of some object or object pointer type.
+ ///
+ /// \param dc The declaration context for which we are building up a
+ /// substitution mapping, which should be an Objective-C class, extension,
+ /// category, or method within.
+ ///
+ /// \returns an array of type arguments that can be substituted for
+ /// the type parameters of the given declaration context in any type described
+ /// within that context, or an empty optional to indicate that no
+ /// substitution is required.
+ Optional<ArrayRef<QualType>>
+ getObjCSubstitutions(const DeclContext *dc) const;
+
+ /// Determines if this is an ObjC interface type that may accept type
+ /// parameters.
+ bool acceptsObjCTypeParams() const;
+
const char *getTypeClassName() const;
QualType getCanonicalTypeInternal() const {
@@ -3497,6 +3611,7 @@ public:
attr_nonnull,
attr_nullable,
attr_null_unspecified,
+ attr_objc_kindof,
};
private:
@@ -4369,19 +4484,25 @@ public:
};
/// ObjCObjectType - Represents a class type in Objective C.
-/// Every Objective C type is a combination of a base type and a
-/// list of protocols.
+///
+/// Every Objective C type is a combination of a base type, a set of
+/// type arguments (optional, for parameterized classes) and a list of
+/// protocols.
///
/// Given the following declarations:
/// \code
-/// \@class C;
+/// \@class C<T>;
/// \@protocol P;
/// \endcode
///
/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType
/// with base C and no protocols.
///
-/// 'C<P>' is an ObjCObjectType with base C and protocol list [P].
+/// 'C<P>' is an unspecialized ObjCObjectType with base C and protocol list [P].
+/// 'C<C*>' is a specialized ObjCObjectType with type arguments 'C*' and no
+/// protocol list.
+/// 'C<C*><P>' is a specialized ObjCObjectType with base C, type arguments 'C*',
+/// and protocol list [P].
///
/// 'id' is a TypedefType which is sugar for an ObjCObjectPointerType whose
/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType
@@ -4391,8 +4512,10 @@ public:
/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually
/// this should get its own sugar class to better represent the source.
class ObjCObjectType : public Type {
- // ObjCObjectType.NumProtocols - the number of protocols stored
+ // ObjCObjectType.NumTypeArgs - the number of type arguments stored
// after the ObjCObjectPointerType node.
+ // ObjCObjectType.NumProtocols - the number of protocols stored
+ // after the type arguments of ObjCObjectPointerType node.
//
// These protocols are those written directly on the type. If
// protocol qualifiers ever become additive, the iterators will need
@@ -4404,23 +4527,38 @@ class ObjCObjectType : public Type {
/// Either a BuiltinType or an InterfaceType or sugar for either.
QualType BaseType;
+ /// Cached superclass type.
+ mutable llvm::PointerIntPair<const ObjCObjectType *, 1, bool>
+ CachedSuperClassType;
+
ObjCProtocolDecl * const *getProtocolStorage() const {
return const_cast<ObjCObjectType*>(this)->getProtocolStorage();
}
+ QualType *getTypeArgStorage();
+ const QualType *getTypeArgStorage() const {
+ return const_cast<ObjCObjectType *>(this)->getTypeArgStorage();
+ }
+
ObjCProtocolDecl **getProtocolStorage();
protected:
ObjCObjectType(QualType Canonical, QualType Base,
- ObjCProtocolDecl * const *Protocols, unsigned NumProtocols);
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf);
enum Nonce_ObjCInterface { Nonce_ObjCInterface };
ObjCObjectType(enum Nonce_ObjCInterface)
: Type(ObjCInterface, QualType(), false, false, false, false),
BaseType(QualType(this_(), 0)) {
ObjCObjectTypeBits.NumProtocols = 0;
+ ObjCObjectTypeBits.NumTypeArgs = 0;
+ ObjCObjectTypeBits.IsKindOf = 0;
}
+ void computeSuperClassTypeSlow() const;
+
public:
/// getBaseType - Gets the base type of this object type. This is
/// always (possibly sugar for) one of:
@@ -4452,6 +4590,33 @@ public:
/// really is an interface.
ObjCInterfaceDecl *getInterface() const;
+ /// Determine whether this object type is "specialized", meaning
+ /// that it has type arguments.
+ bool isSpecialized() const;
+
+ /// Determine whether this object type was written with type arguments.
+ bool isSpecializedAsWritten() const {
+ return ObjCObjectTypeBits.NumTypeArgs > 0;
+ }
+
+ /// Determine whether this object type is "unspecialized", meaning
+ /// that it has no type arguments.
+ bool isUnspecialized() const { return !isSpecialized(); }
+
+ /// Determine whether this object type is "unspecialized" as
+ /// written, meaning that it has no type arguments.
+ bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
+
+ /// Retrieve the type arguments of this object type (semantically).
+ ArrayRef<QualType> getTypeArgs() const;
+
+ /// Retrieve the type arguments of this object type as they were
+ /// written.
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return ArrayRef<QualType>(getTypeArgStorage(),
+ ObjCObjectTypeBits.NumTypeArgs);
+ }
+
typedef ObjCProtocolDecl * const *qual_iterator;
typedef llvm::iterator_range<qual_iterator> qual_range;
@@ -4471,6 +4636,35 @@ public:
return qual_begin()[I];
}
+ /// Retrieve all of the protocol qualifiers.
+ ArrayRef<ObjCProtocolDecl *> getProtocols() const {
+ return ArrayRef<ObjCProtocolDecl *>(qual_begin(), getNumProtocols());
+ }
+
+ /// Whether this is a "__kindof" type as written.
+ bool isKindOfTypeAsWritten() const { return ObjCObjectTypeBits.IsKindOf; }
+
+ /// Whether this ia a "__kindof" type (semantically).
+ bool isKindOfType() const;
+
+ /// Retrieve the type of the superclass of this object type.
+ ///
+ /// This operation substitutes any type arguments into the
+ /// superclass of the current class type, potentially producing a
+ /// specialization of the superclass type. Produces a null type if
+ /// there is no superclass.
+ QualType getSuperClassType() const {
+ if (!CachedSuperClassType.getInt())
+ computeSuperClassTypeSlow();
+
+ assert(CachedSuperClassType.getInt() && "Superclass not set?");
+ return QualType(CachedSuperClassType.getPointer(), 0);
+ }
+
+ /// Strip off the Objective-C "kindof" type and (with it) any
+ /// protocol qualifiers.
+ QualType stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const;
+
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -4491,21 +4685,27 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode {
// will need to be modified.
ObjCObjectTypeImpl(QualType Canonical, QualType Base,
- ObjCProtocolDecl * const *Protocols,
- unsigned NumProtocols)
- : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {}
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf)
+ : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {}
public:
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
QualType Base,
- ObjCProtocolDecl *const *protocols,
- unsigned NumProtocols);
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf);
};
+inline QualType *ObjCObjectType::getTypeArgStorage() {
+ return reinterpret_cast<QualType *>(static_cast<ObjCObjectTypeImpl*>(this)+1);
+}
+
inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
- return reinterpret_cast<ObjCProtocolDecl**>(
- static_cast<ObjCObjectTypeImpl*>(this) + 1);
+ return reinterpret_cast<ObjCProtocolDecl**>(
+ getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs);
}
/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
@@ -4556,9 +4756,14 @@ public:
};
inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
- if (const ObjCInterfaceType *T =
- getBaseType()->getAs<ObjCInterfaceType>())
- return T->getDecl();
+ QualType baseType = getBaseType();
+ while (const ObjCObjectType *ObjT = baseType->getAs<ObjCObjectType>()) {
+ if (const ObjCInterfaceType *T = dyn_cast<ObjCInterfaceType>(ObjT))
+ return T->getDecl();
+
+ baseType = ObjT->getBaseType();
+ }
+
return nullptr;
}
@@ -4575,7 +4780,11 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
ObjCObjectPointerType(QualType Canonical, QualType Pointee)
- : Type(ObjCObjectPointer, Canonical, false, false, false, false),
+ : Type(ObjCObjectPointer, Canonical,
+ Pointee->isDependentType(),
+ Pointee->isInstantiationDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
PointeeType(Pointee) {}
friend class ASTContext; // ASTContext creates these.
@@ -4617,9 +4826,7 @@ public:
/// qualifiers on the interface are ignored.
///
/// \return null if the base type for this pointer is 'id' or 'Class'
- const ObjCInterfaceType *getInterfaceType() const {
- return getObjectType()->getBaseType()->getAs<ObjCInterfaceType>();
- }
+ const ObjCInterfaceType *getInterfaceType() const;
/// getInterfaceDecl - If this pointer points to an Objective \@interface
/// type, gets the declaration for that interface.
@@ -4641,6 +4848,12 @@ public:
return getObjectType()->isObjCUnqualifiedClass();
}
+ /// isObjCIdOrClassType - True if this is equivalent to the 'id' or
+ /// 'Class' type,
+ bool isObjCIdOrClassType() const {
+ return getObjectType()->isObjCUnqualifiedIdOrClass();
+ }
+
/// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some
/// non-empty set of protocols.
bool isObjCQualifiedIdType() const {
@@ -4653,6 +4866,34 @@ public:
return getObjectType()->isObjCQualifiedClass();
}
+ /// Whether this is a "__kindof" type.
+ bool isKindOfType() const { return getObjectType()->isKindOfType(); }
+
+ /// Whether this type is specialized, meaning that it has type arguments.
+ bool isSpecialized() const { return getObjectType()->isSpecialized(); }
+
+ /// Whether this type is specialized, meaning that it has type arguments.
+ bool isSpecializedAsWritten() const {
+ return getObjectType()->isSpecializedAsWritten();
+ }
+
+ /// Whether this type is unspecialized, meaning that is has no type arguments.
+ bool isUnspecialized() const { return getObjectType()->isUnspecialized(); }
+
+ /// Determine whether this object type is "unspecialized" as
+ /// written, meaning that it has no type arguments.
+ bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
+
+ /// Retrieve the type arguments for this type.
+ ArrayRef<QualType> getTypeArgs() const {
+ return getObjectType()->getTypeArgs();
+ }
+
+ /// Retrieve the type arguments for this type.
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return getObjectType()->getTypeArgsAsWritten();
+ }
+
/// An iterator over the qualifiers on the object type. Provided
/// for convenience. This will always iterate over the full set of
/// protocols on a type, not just those provided directly.
@@ -4683,6 +4924,19 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
+ /// Retrieve the type of the superclass of this object pointer type.
+ ///
+ /// This operation substitutes any type arguments into the
+ /// superclass of the current class type, potentially producing a
+ /// pointer to a specialization of the superclass type. Produces a
+ /// null type if there is no superclass.
+ QualType getSuperClassType() const;
+
+ /// Strip off the Objective-C "kindof" type and (with it) any
+ /// protocol qualifiers.
+ const ObjCObjectPointerType *stripObjCKindOfTypeAndQuals(
+ const ASTContext &ctx) const;
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType());
}
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index e29fa4903282..f4d20b8d526a 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -177,6 +177,9 @@ public:
memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
}
+ /// Copies the other type loc into this one.
+ void copy(TypeLoc other);
+
friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data;
}
@@ -185,6 +188,10 @@ public:
return !(LHS == RHS);
}
+ /// Find the location of the nullability specifier (__nonnull,
+ /// __nullable, or __null_unspecifier), if there is one.
+ SourceLocation findNullabilityLoc() const;
+
private:
static bool isKind(const TypeLoc&) {
return true;
@@ -249,6 +256,10 @@ public:
// do nothing
}
+ void copyLocal(TypeLoc other) {
+ // do nothing
+ }
+
TypeLoc getNextTypeLoc() const {
return getUnqualifiedLoc();
}
@@ -339,6 +350,20 @@ public:
return size;
}
+ void copyLocal(Derived other) {
+ // Some subclasses have no data to copy.
+ if (asDerived()->getLocalDataSize() == 0) return;
+
+ // Copy the fixed-sized local data.
+ memcpy(getLocalData(), other.getLocalData(), sizeof(LocalData));
+
+ // Copy the variable-sized local data. We need to do this
+ // separately because the padding in the source and the padding in
+ // the destination might be different.
+ memcpy(getExtraLocalData(), other.getExtraLocalData(),
+ asDerived()->getExtraLocalDataSize());
+ }
+
TypeLoc getNextTypeLoc() const {
return getNextTypeLoc(asDerived()->getInnerType());
}
@@ -799,9 +824,11 @@ public:
};
-struct ObjCProtocolListLocInfo {
- SourceLocation LAngleLoc;
- SourceLocation RAngleLoc;
+struct ObjCObjectTypeLocInfo {
+ SourceLocation TypeArgsLAngleLoc;
+ SourceLocation TypeArgsRAngleLoc;
+ SourceLocation ProtocolLAngleLoc;
+ SourceLocation ProtocolRAngleLoc;
bool HasBaseTypeAsWritten;
};
@@ -813,25 +840,59 @@ struct ObjCProtocolListLocInfo {
class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
ObjCObjectTypeLoc,
ObjCObjectType,
- ObjCProtocolListLocInfo> {
- // SourceLocations are stored after Info, one for each Protocol.
+ ObjCObjectTypeLocInfo> {
+ // TypeSourceInfo*'s are stored after Info, one for each type argument.
+ TypeSourceInfo **getTypeArgLocArray() const {
+ return (TypeSourceInfo**)this->getExtraLocalData();
+ }
+
+ // SourceLocations are stored after the type argument information, one for
+ // each Protocol.
SourceLocation *getProtocolLocArray() const {
- return (SourceLocation*) this->getExtraLocalData();
+ return (SourceLocation*)(getTypeArgLocArray() + getNumTypeArgs());
}
public:
- SourceLocation getLAngleLoc() const {
- return this->getLocalData()->LAngleLoc;
+ SourceLocation getTypeArgsLAngleLoc() const {
+ return this->getLocalData()->TypeArgsLAngleLoc;
}
- void setLAngleLoc(SourceLocation Loc) {
- this->getLocalData()->LAngleLoc = Loc;
+ void setTypeArgsLAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->TypeArgsLAngleLoc = Loc;
}
- SourceLocation getRAngleLoc() const {
- return this->getLocalData()->RAngleLoc;
+ SourceLocation getTypeArgsRAngleLoc() const {
+ return this->getLocalData()->TypeArgsRAngleLoc;
}
- void setRAngleLoc(SourceLocation Loc) {
- this->getLocalData()->RAngleLoc = Loc;
+ void setTypeArgsRAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->TypeArgsRAngleLoc = Loc;
+ }
+
+ unsigned getNumTypeArgs() const {
+ return this->getTypePtr()->getTypeArgsAsWritten().size();
+ }
+
+ TypeSourceInfo *getTypeArgTInfo(unsigned i) const {
+ assert(i < getNumTypeArgs() && "Index is out of bounds!");
+ return getTypeArgLocArray()[i];
+ }
+
+ void setTypeArgTInfo(unsigned i, TypeSourceInfo *TInfo) {
+ assert(i < getNumTypeArgs() && "Index is out of bounds!");
+ getTypeArgLocArray()[i] = TInfo;
+ }
+
+ SourceLocation getProtocolLAngleLoc() const {
+ return this->getLocalData()->ProtocolLAngleLoc;
+ }
+ void setProtocolLAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->ProtocolLAngleLoc = Loc;
+ }
+
+ SourceLocation getProtocolRAngleLoc() const {
+ return this->getLocalData()->ProtocolRAngleLoc;
+ }
+ void setProtocolRAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->ProtocolRAngleLoc = Loc;
}
unsigned getNumProtocols() const {
@@ -852,6 +913,11 @@ public:
return *(this->getTypePtr()->qual_begin() + i);
}
+
+ ArrayRef<SourceLocation> getProtocolLocs() const {
+ return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols());
+ }
+
bool hasBaseTypeAsWritten() const {
return getLocalData()->HasBaseTypeAsWritten;
}
@@ -865,23 +931,27 @@ public:
}
SourceRange getLocalSourceRange() const {
- return SourceRange(getLAngleLoc(), getRAngleLoc());
+ SourceLocation start = getTypeArgsLAngleLoc();
+ if (start.isInvalid())
+ start = getProtocolLAngleLoc();
+ SourceLocation end = getProtocolRAngleLoc();
+ if (end.isInvalid())
+ end = getTypeArgsRAngleLoc();
+ return SourceRange(start, end);
}
- void initializeLocal(ASTContext &Context, SourceLocation Loc) {
- setHasBaseTypeAsWritten(true);
- setLAngleLoc(Loc);
- setRAngleLoc(Loc);
- for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
- setProtocolLoc(i, Loc);
- }
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
unsigned getExtraLocalDataSize() const {
- return this->getNumProtocols() * sizeof(SourceLocation);
+ return this->getNumTypeArgs() * sizeof(TypeSourceInfo *)
+ + this->getNumProtocols() * sizeof(SourceLocation);
}
unsigned getExtraLocalDataAlignment() const {
- return llvm::alignOf<SourceLocation>();
+ assert(llvm::alignOf<ObjCObjectTypeLoc>()
+ >= llvm::alignOf<TypeSourceInfo *>() &&
+ "not enough alignment for tail-allocated data");
+ return llvm::alignOf<TypeSourceInfo *>();
}
QualType getInnerType() const {
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index e7a97a7ff745..281d6370e5c8 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -112,7 +112,7 @@ private:
///
/// FIXME: Do we want to support this now that we have bind()?
template <typename T>
-internal::Matcher<T> id(const std::string &ID,
+internal::Matcher<T> id(StringRef ID,
const internal::BindableMatcher<T> &InnerMatcher) {
return InnerMatcher.bind(ID);
}
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index cbaa4ba27ce7..b494647d79bc 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -140,8 +140,7 @@ public:
};
/// \brief Add a binding from an id to a node.
- void setBinding(const std::string &Id,
- const ast_type_traits::DynTypedNode &DynNode) {
+ void setBinding(StringRef Id, const ast_type_traits::DynTypedNode &DynNode) {
if (Bindings.empty())
Bindings.emplace_back();
for (BoundNodesMap &Binding : Bindings)
diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
index 78aa9dc82a98..c391b24a3330 100644
--- a/include/clang/ASTMatchers/Dynamic/VariantValue.h
+++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -242,7 +242,7 @@ struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
///
/// Supported types:
/// - \c unsigned
-/// - \c std::string
+/// - \c llvm::StringRef
/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
class VariantValue {
public:
@@ -254,7 +254,7 @@ public:
/// \brief Specific constructors for each supported type.
VariantValue(unsigned Unsigned);
- VariantValue(const std::string &String);
+ VariantValue(StringRef String);
VariantValue(const VariantMatcher &Matchers);
/// \brief Returns true iff this is not an empty value.
@@ -269,7 +269,7 @@ public:
/// \brief String value functions.
bool isString() const;
const std::string &getString() const;
- void setString(const std::string &String);
+ void setString(StringRef String);
/// \brief Matcher value functions.
bool isMatcher() const;
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 2bbce37e57bb..fb1eb58dcc70 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -976,6 +976,11 @@ def TypeNullUnspecified : TypeAttr {
let Documentation = [TypeNullUnspecifiedDocs];
}
+def ObjCKindOf : TypeAttr {
+ let Spellings = [Keyword<"__kindof">];
+ let Documentation = [Undocumented];
+}
+
def AssumeAligned : InheritableAttr {
let Spellings = [GCC<"assume_aligned">];
let Subjects = SubjectList<[ObjCMethod, Function]>;
@@ -1276,9 +1281,8 @@ def Pascal : InheritableAttr {
def Target : InheritableAttr {
let Spellings = [GCC<"target">];
let Args = [StringArgument<"features">];
- let Subjects =
- SubjectList<[Function], ErrorDiag, "ExpectedFunctionMethodOrClass">;
- let Documentation = [Undocumented];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [TargetDocs];
}
def TransparentUnion : InheritableAttr {
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index 107458e46145..e4ca0cb4778e 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -678,6 +678,25 @@ The semantics are as follows:
}];
}
+def TargetDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the GNU style ``__attribute__((target("OPTIONS")))`` attribute.
+This attribute may be attached to a function definition and instructs
+the backend to use different code generation options than were passed on the
+command line.
+
+The current set of options correspond to the existing "subtarget features" for
+the target with or without a "-mno-" in front corresponding to the absence
+of the feature, as well as ``arch="CPU"`` which will change the default "CPU"
+for the function.
+
+Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2",
+"avx", "xop" and largely correspond to the machine specific options handled by
+the front end.
+}];
+}
+
def DocCatAMDGPURegisterAttributes :
DocumentationCategory<"AMD GPU Register Attributes"> {
let Content = [{
diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def
index 02e52947ed6c..fdf1cb0b5a40 100644
--- a/include/clang/Basic/BuiltinsPPC.def
+++ b/include/clang/Basic/BuiltinsPPC.def
@@ -248,6 +248,11 @@ BUILTIN(__builtin_altivec_crypto_vpmsumh, "V8UsV8UsV8Us", "")
BUILTIN(__builtin_altivec_crypto_vpmsumw, "V4UiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_crypto_vpmsumd, "V2ULLiV2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_vclzb, "V16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vclzh, "V8UsV8Us", "")
+BUILTIN(__builtin_altivec_vclzw, "V4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vclzd, "V2ULLiV2ULLi", "")
+
// VSX built-ins.
BUILTIN(__builtin_vsx_lxvd2x, "V2divC*", "")
@@ -279,6 +284,47 @@ BUILTIN(__builtin_vsx_xvcmpgesp, "V4UiV4fV4f", "")
BUILTIN(__builtin_vsx_xvcmpgtdp, "V2ULLiV2dV2d", "")
BUILTIN(__builtin_vsx_xvcmpgtsp, "V4UiV4fV4f", "")
+BUILTIN(__builtin_vsx_xvrdpim, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrspim, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrdpi, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrspi, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrdpic, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrspic, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrdpiz, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrspiz, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvmaddadp, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvmaddasp, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvmsubadp, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvmsubasp, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvmuldp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvmulsp, "V4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvnmaddadp, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvnmaddasp, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvnmsubadp, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvnmsubasp, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvredp, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvresp, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrsqrtedp, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrsqrtesp, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvsqrtdp, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvsqrtsp, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xxleqv, "V4UiV4UiV4Ui", "")
+
+BUILTIN(__builtin_vsx_xvcpsgndp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcpsgnsp, "V4fV4fV4f", "")
+
// HTM builtins
BUILTIN(__builtin_tbegin, "UiUIi", "")
BUILTIN(__builtin_tend, "UiUIi", "")
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index aaf279f3713f..1cd8973cbd6d 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -1157,5 +1157,65 @@ BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "")
BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "")
BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "")
BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "")
+BUILTIN(__builtin_ia32_blendmb_128_mask, "V16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_blendmb_256_mask, "V32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_blendmw_128_mask, "V8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_blendmw_256_mask, "V16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_pabsb128_mask, "V16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_pabsb256_mask, "V32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_pabsw128_mask, "V8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_pabsw256_mask, "V16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_packssdw128_mask, "V8sV4iV4iV8sUc", "")
+BUILTIN(__builtin_ia32_packssdw256_mask, "V16sV8iV8iV16sUs", "")
+BUILTIN(__builtin_ia32_packsswb128_mask, "V16cV8sV8sV16cUs", "")
+BUILTIN(__builtin_ia32_packsswb256_mask, "V32cV16sV16sV32cUi", "")
+BUILTIN(__builtin_ia32_packusdw128_mask, "V8sV4iV4iV8sUc", "")
+BUILTIN(__builtin_ia32_packusdw256_mask, "V16sV8iV8iV16sUs", "")
+BUILTIN(__builtin_ia32_packuswb128_mask, "V16cV8sV8sV16cUs", "")
+BUILTIN(__builtin_ia32_packuswb256_mask, "V32cV16sV16sV32cUi", "")
+BUILTIN(__builtin_ia32_paddsb128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_paddsb256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_paddsw128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_paddsw256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_paddusb128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_paddusb256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_paddusw128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_paddusw256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_pavgb128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_pavgb256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_pavgw128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_pavgw256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_pmaxsb128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_pmaxsb256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_pmaxsw128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_pmaxsw256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_pmaxub128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_pmaxub256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_pmaxuw128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_pmaxuw256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_pminsb128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_pminsb256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_pminsw128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_pminsw256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_pminub128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_pminub256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_pminuw128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_pminuw256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_pshufb128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_pshufb256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_psubsb128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_psubsb256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_psubsw128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_psubsw256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_psubusb128_mask, "V16cV16cV16cV16cUs", "")
+BUILTIN(__builtin_ia32_psubusb256_mask, "V32cV32cV32cV32cUi", "")
+BUILTIN(__builtin_ia32_psubusw128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_psubusw256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_vpermi2varhi128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_vpermt2varhi128_mask, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_vpermt2varhi128_maskz, "V8sV8sV8sV8sUc", "")
+BUILTIN(__builtin_ia32_vpermt2varhi256_mask, "V16sV16sV16sV16sUs", "")
+BUILTIN(__builtin_ia32_vpermt2varhi256_maskz, "V16sV16sV16sV16sUs", "")
#undef BUILTIN
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index dece8f9ed2ec..e1a23120c186 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -21,6 +21,7 @@ def Named : Decl<1>;
def TypedefName : DDecl<Type, 1>;
def Typedef : DDecl<TypedefName>;
def TypeAlias : DDecl<TypedefName>;
+ def ObjCTypeParam : DDecl<TypedefName>;
def UnresolvedUsingTypename : DDecl<Type>;
def Tag : DDecl<Type, 1>, DeclContext;
def Enum : DDecl<Tag>;
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 24813c67c2f5..ff42683ecdde 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -179,6 +179,8 @@ def err_target_unsupported_fpmath : Error<
"the '%0' unit is not supported with this instruction set">;
def err_target_unsupported_unaligned : Error<
"the %0 sub-architecture does not support unaligned accesses">;
+def err_opt_not_valid_with_opt : Error<
+ "option '%0' cannot be specified with '%1'">;
// Source manager
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 7c0696a1b922..f7f09da4ea6e 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -69,8 +69,6 @@ def err_drv_no_module_support : Error<
"'%0': unable to use module files with this tool">;
def err_drv_clang_unsupported : Error<
"the clang compiler does not support '%0'">;
-def err_drv_clang_unsupported_per_platform : Error<
- "the clang compiler does not support '%0' on this platform">;
def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error<
"the clang compiler does not support '%0' for C++ on Darwin/i386">;
def err_drv_command_failed : Error<
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 85796cc0d325..4ecd5d5e1842 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -280,6 +280,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 ObjCProtocolQualifiers : DiagGroup<"objc-protocol-qualifiers">;
def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
def ObjCDesignatedInit : DiagGroup<"objc-designated-initializers">;
def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 6a11d240c63c..1364b982ecf1 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -1004,10 +1004,6 @@ def err_pragma_invalid_keyword : Error<
def warn_pragma_unroll_cuda_value_in_parens : Warning<
"argument to '#pragma unroll' should not be in parentheses in CUDA C/C++">,
InGroup<CudaCompat>;
-
-def err_empty_attribute_block : Error<
- "Microsoft attribute block cannot be empty">;
-
} // end of Parse Issue category.
let CategoryName = "Modules Issue" in {
@@ -1017,4 +1013,16 @@ def err_module_expected_semi : Error<
"expected ';' after module name">;
}
+let CategoryName = "Generics Issue" in {
+
+def err_objc_expected_type_parameter : Error<
+ "expected type parameter name">;
+
+def err_objc_parameterized_implementation : Error<
+ "@implementation cannot have type parameters">;
+
+def err_objc_type_args_after_protocols : Error<
+ "protocol qualifiers must precede type arguments">;
+}
+
} // end of Parser diagnostics
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 750219483c6c..fb1e3f1cb46e 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -188,6 +188,8 @@ def ext_flexible_array_init : Extension<
"flexible array initialization is a GNU extension">, InGroup<GNUFlexibleArrayInitializer>;
// Declarations.
+def err_redeclaration_different_type : Error<
+ "redeclaration of %0 with a different type%diff{: $ vs $|}1,2">;
def err_bad_variable_name : Error<
"%0 cannot be the name of a variable or data member">;
def err_bad_parameter_name : Error<
@@ -978,6 +980,12 @@ def warning_multiple_selectors: Warning<
"several methods with selector %0 of mismatched types are found "
"for the @selector expression">,
InGroup<SelectorTypeMismatch>, DefaultIgnore;
+
+def err_objc_kindof_nonobject : Error<
+ "'__kindof' specifier cannot be applied to non-object type %0">;
+def err_objc_kindof_wrong_position : Error<
+ "'__kindof' type specifier must precede the declarator">;
+
// C++ declarations
def err_static_assert_expression_is_not_constant : Error<
"static_assert expression is not an integral constant expression">;
@@ -2131,6 +2139,11 @@ def warn_concatenated_nsarray_literal : Warning<
InGroup<ObjCStringConcatenation>;
def note_objc_literal_comparison_isequal : Note<
"use 'isEqual:' instead">;
+def warn_objc_collection_literal_element : Warning<
+ "object of type %0 is not compatible with "
+ "%select{array element type|dictionary key type|dictionary value type}1 %2">,
+ InGroup<ObjCLiteralConversion>;
+
def err_attribute_argument_is_zero : Error<
"%0 attribute must be greater than 0">;
def warn_attribute_argument_n_negative : Warning<
@@ -2148,6 +2161,10 @@ def warn_objc_redundant_literal_use : Warning<
def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", "
"\"local-dynamic\", \"initial-exec\" or \"local-exec\"">;
+def err_tls_var_aligned_over_maximum : Error<
+ "alignment (%0) of thread-local variable %1 is greater than the maximum supported "
+ "alignment (%2) for a thread-local variable on this target">;
+
def err_only_annotate_after_access_spec : Error<
"access specifier can only have annotation attributes">;
@@ -4740,6 +4757,8 @@ def warn_division_by_zero : Warning<"division by zero is undefined">,
InGroup<DivZero>;
def warn_remainder_by_zero : Warning<"remainder by zero is undefined">,
InGroup<DivZero>;
+def warn_shift_lhs_negative : Warning<"shifting a negative signed value is undefined">,
+ InGroup<DiagGroup<"shift-negative-value">>;
def warn_shift_negative : Warning<"shift count is negative">,
InGroup<DiagGroup<"shift-count-negative">>;
def warn_shift_gt_typewidth : Warning<"shift count >= width of type">,
@@ -5576,6 +5595,8 @@ def err_seh_try_outside_functions : Error<
"cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls">;
def err_mixing_cxx_try_seh_try : Error<
"cannot use C++ 'try' in the same function as SEH '__try'">;
+def err_seh_try_unsupported : Error<
+ "SEH '__try' is not supported on this target">;
def note_conflicting_try_here : Note<
"conflicting %0 here">;
def warn_jump_out_of_seh_finally : Warning<
@@ -7740,6 +7761,84 @@ def warn_nullability_missing : Warning<
"type specifier (_Nonnull, _Nullable, or _Null_unspecified)">,
InGroup<NullabilityCompleteness>;
+def err_type_arg_explicit_nullability : Error<
+ "type argument %0 cannot explicitly specify nullability">;
+
+def err_type_param_bound_explicit_nullability : Error<
+ "type parameter %0 bound %1 cannot explicitly specify nullability">;
+
}
+let CategoryName = "Generics Issue" in {
+
+def err_objc_type_param_bound_nonobject : Error<
+ "type bound %0 for type parameter %1 is not an Objective-C pointer type">;
+
+def err_objc_type_param_bound_missing_pointer : Error<
+ "missing '*' in type bound %0 for type parameter %1">;
+
+def err_objc_type_param_redecl : Error<
+ "redeclaration of type parameter %0">;
+
+def err_objc_type_param_arity_mismatch : Error<
+ "%select{forward class declaration|class definition|category|extension}0 has "
+ "too %select{few|many}1 type parameters (expected %2, have %3)">;
+
+def err_objc_type_param_bound_conflict : Error<
+ "type bound %0 for type parameter %1 conflicts with "
+ "%select{implicit|previous}2 bound %3%select{for type parameter %5|}4">;
+
+def err_objc_type_param_variance_conflict : Error<
+ "%select{in|co|contra}0variant type parameter %1 conflicts with previous "
+ "%select{in|co|contra}2variant type parameter %3">;
+
+def note_objc_type_param_here : Note<"type parameter %0 declared here">;
+
+def err_objc_type_param_bound_missing : Error<
+ "missing type bound %0 for type parameter %1 in %select{@interface|@class}2">;
+
+def err_objc_parameterized_category_nonclass : Error<
+ "%select{extension|category}0 of non-parameterized class %1 cannot have type "
+ "parameters">;
+
+def err_objc_parameterized_forward_class : Error<
+ "forward declaration of non-parameterized class %0 cannot have type "
+ "parameters">;
+
+def err_objc_parameterized_forward_class_first : Error<
+ "class %0 previously declared with type parameters">;
+
+def err_objc_type_arg_missing_star : Error<
+ "type argument %0 must be a pointer (requires a '*')">;
+
+def err_objc_type_arg_missing : Error<
+ "no type or protocol named %0">;
+
+def err_objc_type_args_and_protocols : Error<
+ "angle brackets contain both a %select{type|protocol}0 (%1) and a "
+ "%select{protocol|type}0 (%2)">;
+
+def err_objc_type_args_non_class : Error<
+ "type arguments cannot be applied to non-class type %0">;
+
+def err_objc_type_args_non_parameterized_class : Error<
+ "type arguments cannot be applied to non-parameterized class %0">;
+
+def err_objc_type_args_specialized_class : Error<
+ "type arguments cannot be applied to already-specialized class type %0">;
+
+def err_objc_type_args_wrong_arity : Error<
+ "too %select{many|few}0 type arguments for class %1 (have %2, expected %3)">;
+}
+
+def err_objc_type_arg_not_id_compatible : Error<
+ "type argument %0 is neither an Objective-C object nor a block type">;
+
+def err_objc_type_arg_does_not_match_bound : Error<
+ "type argument %0 does not satisfy the bound (%1) of type parameter %2">;
+
+def warn_objc_redundant_qualified_class_type : Warning<
+ "parameterized class %0 already conforms to the protocols listed; did you "
+ "forget a '*'?">, InGroup<ObjCProtocolQualifiers>;
+
} // end of sema component.
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 33a8b747c62d..1785e04b91ca 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -49,7 +49,7 @@ class IdentifierInfo {
// 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 :11;
+ 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.
@@ -69,7 +69,7 @@ class IdentifierInfo {
// stored externally.
bool IsModulesImport : 1; // True if this is the 'import' contextual
// keyword.
- // 32-bit word is filled.
+ // 30 bit left in 64-bit word.
void *FETokenInfo; // Managed by the language front-end.
llvm::StringMapEntry<IdentifierInfo*> *Entry;
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index b27605b15d28..8d606a12d046 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -161,6 +161,7 @@ LANGOPT(NativeHalfType , 1, 0, "Native half type support")
LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns")
LANGOPT(CUDA , 1, 0, "CUDA")
LANGOPT(OpenMP , 1, 0, "OpenMP support")
+LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
LANGOPT(CUDAIsDevice , 1, 0, "Compiling for CUDA device")
LANGOPT(CUDAAllowHostCallsFromHostDevice, 1, 0, "Allow host device functions to call host functions")
LANGOPT(CUDADisableTargetCallChecks, 1, 0, "Disable checks for call targets (host, device, etc.)")
diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h
index 78c1ddb56f9b..98e70dee45e5 100644
--- a/include/clang/Basic/Sanitizers.h
+++ b/include/clang/Basic/Sanitizers.h
@@ -17,8 +17,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
-
-#include <stdint.h>
+#include "llvm/Support/MathExtras.h"
namespace clang {
@@ -47,22 +46,28 @@ enum SanitizerOrdinal : uint64_t {
}
struct SanitizerSet {
- SanitizerSet();
+ SanitizerSet() : Mask(0) {}
/// \brief Check if a certain (single) sanitizer is enabled.
- bool has(SanitizerMask K) const;
+ bool has(SanitizerMask K) const {
+ assert(llvm::isPowerOf2_64(K));
+ return Mask & K;
+ }
/// \brief Check if one or more sanitizers are enabled.
- bool hasOneOf(SanitizerMask K) const;
+ bool hasOneOf(SanitizerMask K) const { return Mask & K; }
/// \brief Enable or disable a certain (single) sanitizer.
- void set(SanitizerMask K, bool Value);
+ void set(SanitizerMask K, bool Value) {
+ assert(llvm::isPowerOf2_64(K));
+ Mask = Value ? (Mask | K) : (Mask & ~K);
+ }
/// \brief Disable all sanitizers.
- void clear();
+ void clear() { Mask = 0; }
/// \brief Returns true if at least one sanitizer is enabled.
- bool empty() const;
+ bool empty() const { return Mask == 0; }
/// \brief Bitmask of enabled sanitizers.
SanitizerMask Mask;
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index a3bb535fa26f..39f575f90ef8 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -70,6 +70,7 @@ protected:
unsigned char MinGlobalAlign;
unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
unsigned short MaxVectorAlign;
+ unsigned short MaxTLSAlign;
unsigned short SimdDefaultAlign;
const char *DescriptionString;
const char *UserLabelPrefix;
@@ -809,6 +810,21 @@ public:
return TLSSupported;
}
+ /// \brief Return the maximum alignment (in bits) of a TLS variable
+ ///
+ /// Gets the maximum alignment (in bits) of a TLS variable on this target.
+ /// Returns zero if there is no such constraint.
+ unsigned short getMaxTLSAlign() const {
+ return MaxTLSAlign;
+ }
+
+ /// \brief Whether the target supports SEH __try.
+ bool isSEHTrySupported() const {
+ return getTriple().isOSWindows() &&
+ (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64);
+ }
+
/// \brief Return true if {|} are normal characters in the asm string.
///
/// If this returns false (the default), then {abc|xyz} is syntax
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index ed2aa82d17e1..7a91c9f502b7 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -526,6 +526,11 @@ KEYWORD(__bridge_transfer , KEYARC)
KEYWORD(__bridge_retained , KEYARC)
KEYWORD(__bridge_retain , KEYARC)
+// Objective-C keywords.
+KEYWORD(__covariant , KEYOBJC2)
+KEYWORD(__contravariant , KEYOBJC2)
+KEYWORD(__kindof , KEYOBJC2)
+
// Alternate spelling for various tokens. There are GCC extensions in all
// languages, but should not be disabled in strict conformance mode.
ALIAS("__alignof__" , __alignof , KEYALL)
diff --git a/include/clang/CodeGen/ObjectFilePCHContainerOperations.h b/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
new file mode 100644
index 000000000000..4540efb29781
--- /dev/null
+++ b/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
@@ -0,0 +1,43 @@
+//===-- CodeGen/ObjectFilePCHContainerOperations.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_CODEGEN_OBJECT_FILE_PCH_CONTAINER_OPERATIONS_H
+#define LLVM_CLANG_CODEGEN_OBJECT_FILE_PCH_CONTAINER_OPERATIONS_H
+
+#include "clang/Frontend/PCHContainerOperations.h"
+
+namespace clang {
+
+/// \brief A PCHContainerOperations implementation that uses LLVM to
+/// wraps Clang modules inside a COFF, ELF, or Mach-O container.
+class ObjectFilePCHContainerOperations
+ : public PCHContainerOperations {
+ /// \brief Return an ASTConsumer that can be chained with a
+ /// PCHGenerator that produces a wrapper file format
+ /// that also contains full debug info for the module.
+ std::unique_ptr<ASTConsumer>
+ CreatePCHContainerGenerator(
+ DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO,
+ const PreprocessorOptions &PPO, const TargetOptions &TO,
+ const LangOptions &LO, const std::string &MainFileName,
+ const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
+ std::shared_ptr<PCHBuffer> Buffer) const override;
+
+ /// \brief Initialize an llvm::BitstreamReader with the serialized
+ /// AST inside the PCH container Buffer.
+ void ExtractPCH(llvm::MemoryBufferRef Buffer,
+ llvm::BitstreamReader &StreamFile) const override;
+
+
+};
+
+}
+
+
+#endif
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index dd0261c2f3a1..fddd15885e18 100644
--- a/include/clang/Driver/Action.h
+++ b/include/clang/Driver/Action.h
@@ -41,6 +41,8 @@ public:
enum ActionClass {
InputClass = 0,
BindArchClass,
+ CudaDeviceClass,
+ CudaHostClass,
PreprocessJobClass,
PrecompileJobClass,
AnalyzeJobClass,
@@ -71,16 +73,16 @@ private:
unsigned OwnsInputs : 1;
protected:
- Action(ActionClass _Kind, types::ID _Type)
- : Kind(_Kind), Type(_Type), OwnsInputs(true) {}
- Action(ActionClass _Kind, std::unique_ptr<Action> Input, types::ID _Type)
- : Kind(_Kind), Type(_Type), Inputs(1, Input.release()), OwnsInputs(true) {
+ Action(ActionClass Kind, types::ID Type)
+ : Kind(Kind), Type(Type), OwnsInputs(true) {}
+ Action(ActionClass Kind, std::unique_ptr<Action> Input, types::ID Type)
+ : Kind(Kind), Type(Type), Inputs(1, Input.release()), OwnsInputs(true) {
}
- Action(ActionClass _Kind, std::unique_ptr<Action> Input)
- : Kind(_Kind), Type(Input->getType()), Inputs(1, Input.release()),
+ Action(ActionClass Kind, std::unique_ptr<Action> Input)
+ : Kind(Kind), Type(Input->getType()), Inputs(1, Input.release()),
OwnsInputs(true) {}
- Action(ActionClass _Kind, const ActionList &_Inputs, types::ID _Type)
- : Kind(_Kind), Type(_Type), Inputs(_Inputs), OwnsInputs(true) {}
+ Action(ActionClass Kind, const ActionList &Inputs, types::ID Type)
+ : Kind(Kind), Type(Type), Inputs(Inputs), OwnsInputs(true) {}
public:
virtual ~Action();
@@ -108,7 +110,7 @@ class InputAction : public Action {
const llvm::opt::Arg &Input;
public:
- InputAction(const llvm::opt::Arg &_Input, types::ID _Type);
+ InputAction(const llvm::opt::Arg &Input, types::ID Type);
const llvm::opt::Arg &getInputArg() const { return Input; }
@@ -124,7 +126,7 @@ class BindArchAction : public Action {
const char *ArchName;
public:
- BindArchAction(std::unique_ptr<Action> Input, const char *_ArchName);
+ BindArchAction(std::unique_ptr<Action> Input, const char *ArchName);
const char *getArchName() const { return ArchName; }
@@ -133,6 +135,41 @@ public:
}
};
+class CudaDeviceAction : public Action {
+ virtual void anchor();
+ /// GPU architecture to bind -- e.g 'sm_35'.
+ const char *GpuArchName;
+ /// True when action results are not consumed by the host action (e.g when
+ /// -fsyntax-only or --cuda-device-only options are used).
+ bool AtTopLevel;
+
+public:
+ CudaDeviceAction(std::unique_ptr<Action> Input, const char *ArchName,
+ bool AtTopLevel);
+
+ const char *getGpuArchName() const { return GpuArchName; }
+ bool isAtTopLevel() const { return AtTopLevel; }
+
+ static bool classof(const Action *A) {
+ return A->getKind() == CudaDeviceClass;
+ }
+};
+
+class CudaHostAction : public Action {
+ virtual void anchor();
+ ActionList DeviceActions;
+
+public:
+ CudaHostAction(std::unique_ptr<Action> Input,
+ const ActionList &DeviceActions);
+ ~CudaHostAction() override;
+
+ ActionList &getDeviceActions() { return DeviceActions; }
+ const ActionList &getDeviceActions() const { return DeviceActions; }
+
+ static bool classof(const Action *A) { return A->getKind() == CudaHostClass; }
+};
+
class JobAction : public Action {
virtual void anchor();
protected:
diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td
index cf6b76bf29f2..907b16fd5caf 100644
--- a/include/clang/Driver/CLCompatOptions.td
+++ b/include/clang/Driver/CLCompatOptions.td
@@ -188,7 +188,7 @@ def _SLASH_EP : CLFlag<"EP">,
def _SLASH_FA : CLFlag<"FA">,
HelpText<"Output assembly code file during compilation">;
def _SLASH_Fa : CLJoined<"Fa">,
- HelpText<"Output assembly code to this file during compilation">,
+ HelpText<"Output assembly code to this file during compilation (with /FA)">,
MetaVarName<"<file or directory>">;
def _SLASH_fallback : CLCompileFlag<"fallback">,
HelpText<"Fall back to cl.exe if clang-cl fails to compile">;
@@ -198,10 +198,10 @@ def _SLASH_Fe : CLJoined<"Fe">,
HelpText<"Set output executable file or directory (ends in / or \\)">,
MetaVarName<"<file or directory>">;
def _SLASH_Fi : CLCompileJoined<"Fi">,
- HelpText<"Set preprocess output file name">,
+ HelpText<"Set preprocess output file name (with /P)">,
MetaVarName<"<file>">;
def _SLASH_Fo : CLCompileJoined<"Fo">,
- HelpText<"Set output object file, or directory (ends in / or \\)">,
+ HelpText<"Set output object file, or directory (ends in / or \\) (with /c)">,
MetaVarName<"<file or directory>">;
def _SLASH_LD : CLFlag<"LD">, HelpText<"Create DLL">;
def _SLASH_LDd : CLFlag<"LDd">, HelpText<"Create debug DLL">;
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index 15c194b09848..4a67fdb6532a 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -405,12 +405,12 @@ public:
bool IsUsingLTO(const llvm::opt::ArgList &Args) const;
private:
- /// \brief Retrieves a ToolChain for a particular target triple.
+ /// \brief Retrieves a ToolChain for a particular \p Target triple.
///
/// Will cache ToolChains for the life of the driver object, and create them
/// on-demand.
const ToolChain &getToolChain(const llvm::opt::ArgList &Args,
- StringRef DarwinArchName = "") const;
+ const llvm::Triple &Target) const;
/// @}
diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
index 8fc2e8d3a5b9..186244bacf31 100644
--- a/include/clang/Driver/Job.h
+++ b/include/clang/Driver/Job.h
@@ -106,6 +106,9 @@ public:
const char *getExecutable() const { return Executable; }
const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
+
+ /// Print a command argument, and optionally quote it.
+ static void printArg(llvm::raw_ostream &OS, const char *Arg, bool Quote);
};
/// Like Command, but with a fallback which is executed in case
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 6a75b7c2c157..6e5dbf225bb6 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -351,6 +351,12 @@ def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group<clang_i_Group>,
MetaVarName<"<directory>">;
def c : Flag<["-"], "c">, Flags<[DriverOption]>,
HelpText<"Only run preprocess, compile, and assemble steps">;
+def cuda_device_only : Flag<["--"], "cuda-device-only">,
+ HelpText<"Do device-side CUDA compilation only">;
+def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">,
+ Flags<[DriverOption, HelpHidden]>, HelpText<"CUDA GPU architecture">;
+def cuda_host_only : Flag<["--"], "cuda-host-only">,
+ HelpText<"Do host-side CUDA compilation only">;
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">;
@@ -422,13 +428,24 @@ def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">,
def fprofile_instr_generate_EQ : Joined<["-"], "fprofile-instr-generate=">,
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<file>">,
HelpText<"Generate instrumented code to collect execution counts into <file> (overridden by LLVM_PROFILE_FILE env var)">;
-def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>;
+def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>,
+ Flags<[DriverOption]>;
def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use instrumentation data for profile-guided optimization">;
def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Generate coverage mapping to enable code coverage analysis">;
+def fprofile_generate : Flag<["-"], "fprofile-generate">,
+ Alias<fprofile_instr_generate>;
+def fprofile_generate_EQ : Joined<["-"], "fprofile-generate=">,
+ Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<directory>">,
+ HelpText<"Generate instrumented code to collect execution counts into <directory>/default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
+def fprofile_use : Flag<["-"], "fprofile-use">, Group<f_Group>,
+ Alias<fprofile_instr_use>;
+def fprofile_use_EQ : Joined<["-"], "fprofile-use=">,
+ Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<pathname>">,
+ HelpText<"Use instrumentation data for profile-guided optimization. If pathname is a directory, it reads from <pathname>/default.profdata. Otherwise, it reads from file <pathname>.">;
def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable the 'blocks' language feature">;
@@ -522,7 +539,8 @@ def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
Flags<[CC1Option, CoreOption]>, MetaVarName<"<check>">,
HelpText<"Turn on runtime checks for various forms of undefined "
"or suspicious behavior. See user manual for available checks ">;
-def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>;
+def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>,
+ Flags<[CoreOption]>;
def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
Group<f_clang_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Path to blacklist file for sanitizers">;
@@ -547,24 +565,29 @@ def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins
def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Disable origins tracking in MemorySanitizer">;
+def fsanitize_memory_use_after_dtor : Flag<["-"], "fsanitize-memory-use-after-dtor">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable use-after-destroy detection in MemorySanitizer">;
def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-padding=">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Level of field padding for AddressSanitizer">;
-def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>;
+def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>,
+ Flags<[CoreOption]>;
def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">,
- Group<f_clang_Group>;
+ Group<f_clang_Group>, Flags<[CoreOption]>;
def fsanitize_recover_EQ : CommaJoined<["-"], "fsanitize-recover=">,
Group<f_clang_Group>,
- Flags<[CC1Option]>,
+ Flags<[CC1Option, CoreOption]>,
HelpText<"Enable recovery for specified sanitizers">;
def fno_sanitize_recover_EQ
: CommaJoined<["-"], "fno-sanitize-recover=">,
- Group<f_clang_Group>,
+ Group<f_clang_Group>, Flags<[CoreOption]>,
HelpText<"Disable recovery for specified sanitizers">;
def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Group>,
Flags<[CC1Option, CoreOption]>,
HelpText<"Enable trapping for specified sanitizers">;
def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>,
+ Flags<[CoreOption]>,
HelpText<"Disable trapping for specified sanitizers">;
def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">,
Group<f_clang_Group>;
@@ -641,7 +664,7 @@ def flat__namespace : Flag<["-"], "flat_namespace">;
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def flto_EQ : Joined<["-"], "flto=">, Group<clang_ignored_gcc_optimization_f_Group>;
-def flto : Flag<["-"], "flto">, Group<f_Group>;
+def flto : Flag<["-"], "flto">, Flags<[CC1Option]>, Group<f_Group>;
def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>;
def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
Group<f_Group>, Flags<[DriverOption, CoreOption]>;
@@ -879,6 +902,8 @@ def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>;
def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>;
+def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>, Flags<[NoArgumentUnused]>;
+def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
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 force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
@@ -904,7 +929,6 @@ def fpie : Flag<["-"], "fpie">, Group<f_Group>;
def fno_pie : Flag<["-"], "fno-pie">, Group<f_Group>;
def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group<f_Group>;
def fno_profile_arcs : Flag<["-"], "fno-profile-arcs">, Group<f_Group>;
-def fprofile_generate : Flag<["-"], "fprofile-generate">, Group<f_Group>;
def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>;
def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group<clang_ignored_f_Group>;
def freg_struct_return : Flag<["-"], "freg-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
@@ -1518,7 +1542,8 @@ def print_libgcc_file_name : Flag<["-", "--"], "print-libgcc-file-name">,
HelpText<"Print the library path for \"libgcc.a\"">;
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">;
+def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
+ Flags<[Unsupported]>;
def print_prog_name_EQ : Joined<["-", "--"], "print-prog-name=">,
HelpText<"Print the full program path of <name>">, MetaVarName<"<name>">;
def print_search_dirs : Flag<["-", "--"], "print-search-dirs">,
@@ -1527,6 +1552,7 @@ def private__bundle : Flag<["-"], "private_bundle">;
def pthreads : Flag<["-"], "pthreads">;
def pthread : Flag<["-"], "pthread">, Flags<[CC1Option]>,
HelpText<"Support POSIX threads in generated code">;
+def no_pthread : Flag<["-"], "no-pthread">, Flags<[CC1Option]>;
def p : Flag<["-"], "p">;
def pie : Flag<["-"], "pie">;
def read__only__relocs : Separate<["-"], "read_only_relocs">;
@@ -1793,8 +1819,6 @@ defm : BooleanFFlag<"keep-inline-functions">, Group<clang_ignored_gcc_optimizati
def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_gcc_optimization_f_Group>;
-defm profile_use : BooleanFFlag<"profile-use">, Group<clang_ignored_gcc_optimization_f_Group>;
-def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Group<clang_ignored_gcc_optimization_f_Group>;
def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>;
defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h
index 11bfd417e1ea..82b668ac883a 100644
--- a/include/clang/Driver/SanitizerArgs.h
+++ b/include/clang/Driver/SanitizerArgs.h
@@ -29,6 +29,7 @@ class SanitizerArgs {
std::vector<std::string> BlacklistFiles;
int CoverageFeatures;
int MsanTrackOrigins;
+ bool MsanUseAfterDtor;
int AsanFieldPadding;
bool AsanZeroBaseShadow;
bool AsanSharedRuntime;
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index 4b696ae5e053..d1b69151b062 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -44,6 +44,7 @@ TYPE("c", C, PP_C, "c", "u")
TYPE("cl", CL, PP_C, "cl", "u")
TYPE("cuda-cpp-output", PP_CUDA, INVALID, "cui", "u")
TYPE("cuda", CUDA, PP_CUDA, "cu", "u")
+TYPE("cuda", CUDA_DEVICE, PP_CUDA, "cu", "")
TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", "u")
TYPE("objective-c", ObjC, PP_ObjC, "m", "u")
diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h
index 34442eb6379f..dd95d6599156 100644
--- a/include/clang/Driver/Types.h
+++ b/include/clang/Driver/Types.h
@@ -63,6 +63,9 @@ namespace types {
/// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
bool isCXX(ID Id);
+ /// isCuda - Is this a CUDA input.
+ bool isCuda(ID Id);
+
/// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
bool isObjC(ID Id);
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 6f9523cdc1ba..f8c8c373e143 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -166,6 +166,9 @@ struct FormatStyle {
/// Like \c Attach, but break before braces on function, namespace and
/// class definitions.
BS_Linux,
+ /// Like ``Attach``, but break before braces on enum, function, and record
+ /// definitions.
+ BS_Mozilla,
/// Like \c Attach, but break before function definitions, and 'else'.
BS_Stroustrup,
/// Always break before braces.
@@ -290,6 +293,12 @@ struct FormatStyle {
/// \brief Language, this format style is targeted at.
LanguageKind Language;
+ /// \brief A regular expression matching macros that start a block.
+ std::string MacroBlockBegin;
+
+ /// \brief A regular expression matching macros that end a block.
+ std::string MacroBlockEnd;
+
/// \brief The maximum number of consecutive empty lines to keep.
unsigned MaxEmptyLinesToKeep;
@@ -479,6 +488,8 @@ struct FormatStyle {
IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
KeepEmptyLinesAtTheStartOfBlocks ==
R.KeepEmptyLinesAtTheStartOfBlocks &&
+ MacroBlockBegin == R.MacroBlockBegin &&
+ MacroBlockEnd == R.MacroBlockEnd &&
MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
NamespaceIndentation == R.NamespaceIndentation &&
ObjCBlockIndentWidth == R.ObjCBlockIndentWidth &&
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index d34cf0cad1c9..803d0233046d 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Frontend/CodeGenOptions.def
@@ -67,6 +67,8 @@ CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is
CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to
///< be generated.
+CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the
+ ///< compile step.
CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants.
CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled.
CODEGENOPT(MSVolatile , 1, 0) ///< Set when /volatile:ms is enabled.
@@ -110,6 +112,8 @@ CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero
///< offset in AddressSanitizer.
CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
///< MemorySanitizer
+CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection
+ ///< in MemorySanitizer
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
///< instrumentation.
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index 66597bd0af8e..53246bcf22c1 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -155,6 +155,7 @@ public:
std::vector<std::string> DependentLibraries;
/// Name of the profile file to use as output for -fprofile-instr-generate
+ /// and -fprofile-generate.
std::string InstrProfileOutput;
/// Name of the profile file to use with -fprofile-sample-use.
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 9cd806c99b85..2f3e1b6cebb1 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -30,6 +30,7 @@
namespace llvm {
class raw_fd_ostream;
class Timer;
+class TimerGroup;
}
namespace clang {
@@ -101,7 +102,10 @@ class CompilerInstance : public ModuleLoader {
/// \brief The semantic analysis object.
std::unique_ptr<Sema> TheSema;
- /// \brief The frontend timer
+ /// \brief The frontend timer group.
+ std::unique_ptr<llvm::TimerGroup> FrontendTimerGroup;
+
+ /// \brief The frontend timer.
std::unique_ptr<llvm::Timer> FrontendTimer;
/// \brief The ASTReader, if one exists.
@@ -157,9 +161,10 @@ class CompilerInstance : public ModuleLoader {
std::string TempFilename;
std::unique_ptr<raw_ostream> OS;
- OutputFile(const std::string &filename, const std::string &tempFilename,
+ OutputFile(std::string filename, std::string tempFilename,
std::unique_ptr<raw_ostream> OS)
- : Filename(filename), TempFilename(tempFilename), OS(std::move(OS)) {}
+ : Filename(std::move(filename)), TempFilename(std::move(tempFilename)),
+ OS(std::move(OS)) {}
OutputFile(OutputFile &&O)
: Filename(std::move(O.Filename)),
TempFilename(std::move(O.TempFilename)), OS(std::move(O.OS)) {}
@@ -614,7 +619,7 @@ public:
///
/// \return - The new object on success, or null on failure.
static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource(
- StringRef Path, const std::string &Sysroot, bool DisablePCHValidation,
+ StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
const PCHContainerOperations &PCHContainerOps,
void *DeserializationListener, bool OwnDeserializationListener,
@@ -627,11 +632,9 @@ public:
/// Create a code completion consumer to print code completion results, at
/// \p Filename, \p Line, and \p Column, to the given output stream \p OS.
- static CodeCompleteConsumer *
- createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename,
- unsigned Line, unsigned Column,
- const CodeCompleteOptions &Opts,
- raw_ostream &OS);
+ static CodeCompleteConsumer *createCodeCompletionConsumer(
+ Preprocessor &PP, StringRef Filename, unsigned Line, unsigned Column,
+ const CodeCompleteOptions &Opts, raw_ostream &OS);
/// \brief Create the Sema object to be used for parsing.
void createSema(TranslationUnitKind TUKind,
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index 2b18a7df53dd..0b03c4aa1cd7 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -452,9 +452,13 @@ public:
/// \param HomeDir The directory in which relative paths within this module
/// map file will be resolved.
///
+ /// \param ExternModuleLoc The location of the "extern module" declaration
+ /// that caused us to load this module map file, if any.
+ ///
/// \returns true if an error occurred, false otherwise.
bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
- const DirectoryEntry *HomeDir);
+ const DirectoryEntry *HomeDir,
+ SourceLocation ExternModuleLoc = SourceLocation());
/// \brief Dump the contents of the module map, for debugging purposes.
void dump();
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index bba0c38cec77..b2f58ead0e75 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -786,6 +786,22 @@ public:
(!getLangOpts().Modules || (bool)getMacroDefinition(II));
}
+ /// \brief Determine whether II is defined as a macro within the module M,
+ /// if that is a module that we've already preprocessed. Does not check for
+ /// macros imported into M.
+ bool isMacroDefinedInLocalModule(const IdentifierInfo *II, Module *M) {
+ if (!II->hasMacroDefinition())
+ return false;
+ auto I = Submodules.find(M);
+ if (I == Submodules.end())
+ return false;
+ auto J = I->second.Macros.find(II);
+ if (J == I->second.Macros.end())
+ return false;
+ auto *MD = J->second.getLatest();
+ return MD && MD->isDefined();
+ }
+
MacroDefinition getMacroDefinition(const IdentifierInfo *II) {
if (!II->hasMacroDefinition())
return MacroDefinition();
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 97a0aa482d2b..fb9eb8ff5af8 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -46,6 +46,8 @@ namespace clang {
class PoisonSEHIdentifiersRAIIObject;
class VersionTuple;
class OMPClause;
+ class ObjCTypeParamList;
+ class ObjCTypeParameter;
/// Parser - This implements a parser for the C family of languages. After
/// parsing units of the grammar, productions are invoked to handle whatever has
@@ -1246,6 +1248,13 @@ private:
DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
ParsedAttributes &prefixAttrs);
+ ObjCTypeParamList *parseObjCTypeParamList();
+ ObjCTypeParamList *parseObjCTypeParamListOrProtocolRefs(
+ SourceLocation &lAngleLoc,
+ SmallVectorImpl<IdentifierLocPair> &protocolIdents,
+ SourceLocation &rAngleLoc,
+ bool mayBeProtocolList = true);
+
void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
BalancedDelimiterTracker &T,
SmallVectorImpl<Decl *> &AllIvarDecls,
@@ -1258,8 +1267,48 @@ private:
bool WarnOnDeclarations,
bool ForObjCContainer,
SourceLocation &LAngleLoc,
- SourceLocation &EndProtoLoc);
- bool ParseObjCProtocolQualifiers(DeclSpec &DS);
+ SourceLocation &EndProtoLoc,
+ bool consumeLastToken);
+
+ /// Parse the first angle-bracket-delimited clause for an
+ /// Objective-C object or object pointer type, which may be either
+ /// type arguments or protocol qualifiers.
+ void parseObjCTypeArgsOrProtocolQualifiers(
+ ParsedType baseType,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SmallVectorImpl<SourceLocation> &protocolLocs,
+ SourceLocation &protocolRAngleLoc,
+ bool consumeLastToken,
+ bool warnOnIncompleteProtocols);
+
+ /// Parse either Objective-C type arguments or protocol qualifiers; if the
+ /// former, also parse protocol qualifiers afterward.
+ void parseObjCTypeArgsAndProtocolQualifiers(
+ ParsedType baseType,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SmallVectorImpl<SourceLocation> &protocolLocs,
+ SourceLocation &protocolRAngleLoc,
+ bool consumeLastToken);
+
+ /// Parse a protocol qualifier type such as '<NSCopying>', which is
+ /// an anachronistic way of writing 'id<NSCopying>'.
+ TypeResult parseObjCProtocolQualifierType(SourceLocation &rAngleLoc);
+
+ /// Parse Objective-C type arguments and protocol qualifiers, extending the
+ /// current type with the parsed result.
+ TypeResult parseObjCTypeArgsAndProtocolQualifiers(SourceLocation loc,
+ ParsedType type,
+ bool consumeLastToken,
+ SourceLocation &endLoc);
+
void ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
Decl *CDecl);
DeclGroupPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
@@ -2469,7 +2518,8 @@ private:
typedef SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
bool ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
- bool ConsumeLastToken);
+ bool ConsumeLastToken,
+ bool ObjCGenericList);
bool ParseTemplateIdAfterTemplateName(TemplateTy Template,
SourceLocation TemplateNameLoc,
const CXXScopeSpec &SS,
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index de65c43c76b2..97022738d03e 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -765,11 +765,13 @@ public:
/// \param Allocator The allocator that will be used to allocate the
/// string itself.
CodeCompletionString *CreateCodeCompletionString(Sema &S,
+ const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments);
CodeCompletionString *CreateCodeCompletionString(ASTContext &Ctx,
Preprocessor &PP,
+ const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments);
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index d375ec303785..41d490063299 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -373,14 +373,6 @@ private:
// Scope specifier for the type spec, if applicable.
CXXScopeSpec TypeScope;
- // List of protocol qualifiers for objective-c classes. Used for
- // protocol-qualified interfaces "NString<foo>" and protocol-qualified id
- // "id<foo>".
- Decl * const *ProtocolQualifiers;
- unsigned NumProtocolQualifiers;
- SourceLocation ProtocolLAngleLoc;
- SourceLocation *ProtocolLocs;
-
// SourceLocation info. These are null if the item wasn't specified or if
// the setting was synthesized.
SourceRange Range;
@@ -442,16 +434,10 @@ public:
Constexpr_specified(false),
Concept_specified(false),
Attrs(attrFactory),
- ProtocolQualifiers(nullptr),
- NumProtocolQualifiers(0),
- ProtocolLocs(nullptr),
writtenBS(),
ObjCQualifiers(nullptr) {
}
- ~DeclSpec() {
- delete [] ProtocolQualifiers;
- delete [] ProtocolLocs;
- }
+
// storage-class-specifier
SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
TSCS getThreadStorageClassSpec() const {
@@ -490,6 +476,8 @@ public:
bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; }
bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
bool isTypeSpecOwned() const { return TypeSpecOwned; }
+ bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
+
ParsedType getRepAsType() const {
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
return TypeRep;
@@ -751,19 +739,6 @@ public:
Attrs.takeAllFrom(attrs);
}
- typedef Decl * const *ProtocolQualifierListTy;
- ProtocolQualifierListTy getProtocolQualifiers() const {
- return ProtocolQualifiers;
- }
- SourceLocation *getProtocolLocs() const { return ProtocolLocs; }
- unsigned getNumProtocolQualifiers() const {
- return NumProtocolQualifiers;
- }
- SourceLocation getProtocolLAngleLoc() const { return ProtocolLAngleLoc; }
- void setProtocolQualifiers(Decl * const *Protos, unsigned NP,
- SourceLocation *ProtoLocs,
- SourceLocation LAngleLoc);
-
/// Finish - This does final analysis of the declspec, issuing diagnostics for
/// things like "_Imaginary" (lacking an FP type). After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 72a0e0b19e3d..db7b6f954c1b 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1387,7 +1387,8 @@ public:
/// Determine if \p D has a visible definition. If not, suggest a declaration
/// that should be made visible to expose the definition.
- bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested);
+ bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
+ bool OnlyNeedComplete = false);
bool hasVisibleDefinition(const NamedDecl *D) {
NamedDecl *Hidden;
return hasVisibleDefinition(const_cast<NamedDecl*>(D), &Hidden);
@@ -1848,7 +1849,7 @@ public:
bool isAcceptableTagRedeclaration(const TagDecl *Previous,
TagTypeKind NewTag, bool isDefinition,
SourceLocation NewTagLoc,
- const IdentifierInfo &Name);
+ const IdentifierInfo *Name);
enum TagUseKind {
TUK_Reference, // Reference to a tag: 'struct foo *X;'
@@ -2187,6 +2188,7 @@ public:
void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
QualType FromType, QualType ToType);
+ void maybeExtendBlockObject(ExprResult &E);
CastKind PrepareCastToObjCObjectPointer(ExprResult &E);
bool CheckPointerConversion(Expr *From, QualType ToType,
CastKind &Kind,
@@ -7088,16 +7090,44 @@ public:
};
ObjCContainerKind getObjCContainerKind() const;
- Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+ DeclResult actOnObjCTypeParam(Scope *S,
+ ObjCTypeParamVariance variance,
+ SourceLocation varianceLoc,
+ unsigned index,
+ IdentifierInfo *paramName,
+ SourceLocation paramLoc,
+ SourceLocation colonLoc,
+ ParsedType typeBound);
+
+ ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
+ ArrayRef<Decl *> typeParams,
+ SourceLocation rAngleLoc);
+ void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
+
+ Decl *ActOnStartClassInterface(Scope *S,
+ SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName,
SourceLocation ClassLoc,
+ ObjCTypeParamList *typeParamList,
IdentifierInfo *SuperName,
SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs,
+ SourceRange SuperTypeArgsRange,
Decl * const *ProtoRefs,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList);
+
+ void ActOnSuperClassOfClassInterface(Scope *S,
+ SourceLocation AtInterfaceLoc,
+ ObjCInterfaceDecl *IDecl,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs,
+ SourceRange SuperTypeArgsRange);
void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
IdentifierInfo *SuperName,
@@ -7124,6 +7154,7 @@ public:
Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName,
SourceLocation ClassLoc,
+ ObjCTypeParamList *typeParamList,
IdentifierInfo *CategoryName,
SourceLocation CategoryLoc,
Decl * const *ProtoRefs,
@@ -7147,9 +7178,10 @@ public:
ArrayRef<Decl *> Decls);
DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
- IdentifierInfo **IdentList,
- SourceLocation *IdentLocs,
- unsigned NumElts);
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ ArrayRef<ObjCTypeParamList *> TypeParamLists,
+ unsigned NumElts);
DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
const IdentifierLocPair *IdentList,
@@ -7161,6 +7193,61 @@ public:
unsigned NumProtocols,
SmallVectorImpl<Decl *> &Protocols);
+ /// Given a list of identifiers (and their locations), resolve the
+ /// names to either Objective-C protocol qualifiers or type
+ /// arguments, as appropriate.
+ void actOnObjCTypeArgsOrProtocolQualifiers(
+ Scope *S,
+ ParsedType baseType,
+ SourceLocation lAngleLoc,
+ ArrayRef<IdentifierInfo *> identifiers,
+ ArrayRef<SourceLocation> identifierLocs,
+ SourceLocation rAngleLoc,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SourceLocation &protocolRAngleLoc,
+ bool warnOnIncompleteProtocols);
+
+ /// Build a an Objective-C protocol-qualified 'id' type where no
+ /// base type was specified.
+ TypeResult actOnObjCProtocolQualifierType(
+ SourceLocation lAngleLoc,
+ ArrayRef<Decl *> protocols,
+ ArrayRef<SourceLocation> protocolLocs,
+ SourceLocation rAngleLoc);
+
+ /// Build a specialized and/or protocol-qualified Objective-C type.
+ TypeResult actOnObjCTypeArgsAndProtocolQualifiers(
+ Scope *S,
+ SourceLocation Loc,
+ ParsedType BaseType,
+ SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<ParsedType> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<Decl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc);
+
+ /// Build an Objective-C object pointer type.
+ QualType BuildObjCObjectType(QualType BaseType,
+ SourceLocation Loc,
+ SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<TypeSourceInfo *> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ 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.
@@ -7610,13 +7697,13 @@ private:
void DestroyDataSharingAttributesStack();
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op,
OpenMPClauseKind CKind);
- /// \brief Checks if the specified variable is used in one of the private
+public:
+ /// \brief Check if the specified variable is used in a private clause in
+ /// Checks if the specified variable is used in one of the private
/// clauses in OpenMP constructs.
bool IsOpenMPCapturedVar(VarDecl *VD);
-public:
- /// \brief Check if the specified variable is used in one of the private
- /// clauses in OpenMP constructs.
+ /// OpenMP constructs.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
bool isOpenMPPrivateVar(VarDecl *VD, unsigned Level);
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h
index b822b11126ea..416ef7b1a682 100644
--- a/include/clang/Sema/Template.h
+++ b/include/clang/Sema/Template.h
@@ -413,6 +413,7 @@ namespace clang {
#define LINKAGESPEC(DERIVED, BASE)
#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
#define OBJCMETHOD(DERIVED, BASE)
+#define OBJCTYPEPARAM(DERIVED, BASE)
#define OBJCIVAR(DERIVED, BASE)
#define OBJCPROPERTY(DERIVED, BASE)
#define OBJCPROPERTYIMPL(DERIVED, BASE)
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index ee8e3f4c6712..4b662077c3c8 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1105,7 +1105,9 @@ namespace clang {
/// \brief An OMPThreadPrivateDecl record.
DECL_OMP_THREADPRIVATE,
/// \brief An EmptyDecl record.
- DECL_EMPTY
+ DECL_EMPTY,
+ /// \brief An ObjCTypeParamDecl record.
+ DECL_OBJC_TYPE_PARAM,
};
/// \brief Record codes for each kind of statement or expression.
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index ef5b107a2fda..9377dfac99cc 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -42,6 +42,7 @@
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Timer.h"
#include <deque>
#include <map>
#include <memory>
@@ -380,6 +381,9 @@ private:
/// \brief The module manager which manages modules and their dependencies
ModuleManager ModuleMgr;
+ /// \brief A timer used to track the time spent deserializing.
+ std::unique_ptr<llvm::Timer> ReadTimer;
+
/// \brief The location where the module file will be considered as
/// imported from. For non-module AST types it should be invalid.
SourceLocation CurrentImportLoc;
@@ -976,12 +980,14 @@ private:
MergedLookups;
typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> >
- MergedDeclsMap;
+ KeyDeclsMap;
- /// \brief A mapping from canonical declarations to the set of additional
- /// (global, previously-canonical) declaration IDs that have been merged with
- /// that canonical declaration.
- MergedDeclsMap MergedDecls;
+ /// \brief A mapping from canonical declarations to the set of global
+ /// declaration IDs for key declaration that have been merged with that
+ /// canonical declaration. A key declaration is a formerly-canonical
+ /// declaration whose module did not import any other key declaration for that
+ /// entity. These are the IDs that we use as keys when finding redecl chains.
+ KeyDeclsMap KeyDecls;
/// \brief A mapping from DeclContexts to the semantic DeclContext that we
/// are treating as the definition of the entity. This is used, for instance,
@@ -1054,6 +1060,36 @@ public:
void ResolveImportedPath(ModuleFile &M, std::string &Filename);
static void ResolveImportedPath(std::string &Filename, StringRef Prefix);
+ /// \brief Returns the first key declaration for the given declaration. This
+ /// is one that is formerly-canonical (or still canonical) and whose module
+ /// did not import any other key declaration of the entity.
+ Decl *getKeyDeclaration(Decl *D) {
+ D = D->getCanonicalDecl();
+ if (D->isFromASTFile())
+ return D;
+
+ auto I = KeyDecls.find(D);
+ if (I == KeyDecls.end() || I->second.empty())
+ return D;
+ return GetExistingDecl(I->second[0]);
+ }
+ const Decl *getKeyDeclaration(const Decl *D) {
+ return getKeyDeclaration(const_cast<Decl*>(D));
+ }
+
+ /// \brief Run a callback on each imported key declaration of \p D.
+ template <typename Fn>
+ void forEachImportedKeyDecl(const Decl *D, Fn Visit) {
+ D = D->getCanonicalDecl();
+ if (D->isFromASTFile())
+ Visit(D);
+
+ auto It = KeyDecls.find(const_cast<Decl*>(D));
+ if (It != KeyDecls.end())
+ for (auto ID : It->second)
+ Visit(GetExistingDecl(ID));
+ }
+
private:
struct ImportedModule {
ModuleFile *Mod;
@@ -1124,18 +1160,6 @@ private:
/// merged into its redecl chain.
Decl *getMostRecentExistingDecl(Decl *D);
- template <typename Fn>
- void forEachFormerlyCanonicalImportedDecl(const Decl *D, Fn Visit) {
- D = D->getCanonicalDecl();
- if (D->isFromASTFile())
- Visit(D);
-
- auto It = MergedDecls.find(const_cast<Decl*>(D));
- if (It != MergedDecls.end())
- for (auto ID : It->second)
- Visit(GetExistingDecl(ID));
- }
-
RecordLocation DeclCursorForID(serialization::DeclID ID,
unsigned &RawLocation);
void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
@@ -1261,12 +1285,16 @@ public:
///
/// \param UseGlobalIndex If true, the AST reader will try to load and use
/// the global module index.
+ ///
+ /// \param ReadTimer If non-null, a timer used to track the time spent
+ /// deserializing.
ASTReader(Preprocessor &PP, ASTContext &Context,
const PCHContainerOperations &PCHContainerOps,
StringRef isysroot = "", bool DisableValidation = false,
bool AllowASTWithCompilerErrors = false,
bool AllowConfigurationMismatch = false,
- bool ValidateSystemInputs = false, bool UseGlobalIndex = true);
+ bool ValidateSystemInputs = false, bool UseGlobalIndex = true,
+ std::unique_ptr<llvm::Timer> ReadTimer = {});
~ASTReader() override;
@@ -1690,7 +1718,7 @@ public:
/// \brief Notify ASTReader that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
- void StartedDeserializing() override { ++NumCurrentElementsDeserializing; }
+ void StartedDeserializing() override;
/// \brief Notify ASTReader that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index c966d3edeb9f..e830fdcf8f20 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -398,7 +398,7 @@ private:
/// \brief The set of declarations that may have redeclaration chains that
/// need to be serialized.
- llvm::SmallSetVector<Decl *, 4> Redeclarations;
+ llvm::SmallVector<const Decl *, 16> Redeclarations;
/// \brief Statements that we've encountered while serializing a
/// declaration or type.
diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
index ca68a74fef96..c9724c08da2d 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
@@ -64,6 +64,9 @@
#endif
namespace clang {
+class DiagnosticsEngine;
+class AnalyzerOptions;
+
namespace ento {
class CheckerOptInfo;
@@ -118,6 +121,10 @@ public:
void initializeManager(CheckerManager &mgr,
SmallVectorImpl<CheckerOptInfo> &opts) const;
+ /// Check if every option corresponds to a specific checker or package.
+ void validateCheckerOptions(const AnalyzerOptions &opts,
+ DiagnosticsEngine &diags) 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 ;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 5a91f074c4e1..fb9630180dca 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1917,11 +1917,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
// We can use protocol_iterator here instead of
// all_referenced_protocol_iterator since we are walking all categories.
for (auto *Proto : OI->all_referenced_protocols()) {
- Protocols.insert(Proto->getCanonicalDecl());
- for (auto *P : Proto->protocols()) {
- Protocols.insert(P->getCanonicalDecl());
- CollectInheritedProtocols(P, Protocols);
- }
+ CollectInheritedProtocols(Proto, Protocols);
}
// Categories of this Interface.
@@ -1935,16 +1931,16 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
}
} else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
for (auto *Proto : OC->protocols()) {
- Protocols.insert(Proto->getCanonicalDecl());
- for (const auto *P : Proto->protocols())
- CollectInheritedProtocols(P, Protocols);
+ CollectInheritedProtocols(Proto, Protocols);
}
} else if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) {
- for (auto *Proto : OP->protocols()) {
- Protocols.insert(Proto->getCanonicalDecl());
- for (const auto *P : Proto->protocols())
- CollectInheritedProtocols(P, Protocols);
- }
+ // Insert the protocol.
+ if (!Protocols.insert(
+ const_cast<ObjCProtocolDecl *>(OP->getCanonicalDecl())).second)
+ return;
+
+ for (auto *Proto : OP->protocols())
+ CollectInheritedProtocols(Proto, Protocols);
}
}
@@ -3618,45 +3614,89 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
QualType ASTContext::getObjCObjectType(QualType BaseType,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) const {
- // If the base type is an interface and there aren't any protocols
- // to add, then the interface type will do just fine.
- if (!NumProtocols && isa<ObjCInterfaceType>(BaseType))
- return BaseType;
+ return getObjCObjectType(BaseType, { },
+ llvm::makeArrayRef(Protocols, NumProtocols),
+ /*isKindOf=*/false);
+}
+
+QualType ASTContext::getObjCObjectType(
+ QualType baseType,
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf) const {
+ // If the base type is an interface and there aren't any protocols or
+ // type arguments to add, then the interface type will do just fine.
+ if (typeArgs.empty() && protocols.empty() && !isKindOf &&
+ isa<ObjCInterfaceType>(baseType))
+ return baseType;
// Look in the folding set for an existing type.
llvm::FoldingSetNodeID ID;
- ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols);
+ ObjCObjectTypeImpl::Profile(ID, baseType, typeArgs, protocols, isKindOf);
void *InsertPos = nullptr;
if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
- // Build the canonical type, which has the canonical base type and
- // a sorted-and-uniqued list of protocols.
- QualType Canonical;
- bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols);
- if (!ProtocolsSorted || !BaseType.isCanonical()) {
- if (!ProtocolsSorted) {
- SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
- Protocols + NumProtocols);
- unsigned UniqueCount = NumProtocols;
-
- SortAndUniqueProtocols(&Sorted[0], UniqueCount);
- Canonical = getObjCObjectType(getCanonicalType(BaseType),
- &Sorted[0], UniqueCount);
+ // Determine the type arguments to be used for canonicalization,
+ // which may be explicitly specified here or written on the base
+ // type.
+ ArrayRef<QualType> effectiveTypeArgs = typeArgs;
+ if (effectiveTypeArgs.empty()) {
+ if (auto baseObject = baseType->getAs<ObjCObjectType>())
+ effectiveTypeArgs = baseObject->getTypeArgs();
+ }
+
+ // Build the canonical type, which has the canonical base type and a
+ // sorted-and-uniqued list of protocols and the type arguments
+ // canonicalized.
+ QualType canonical;
+ bool typeArgsAreCanonical = std::all_of(effectiveTypeArgs.begin(),
+ effectiveTypeArgs.end(),
+ [&](QualType type) {
+ return type.isCanonical();
+ });
+ bool protocolsSorted = areSortedAndUniqued(protocols.data(),
+ protocols.size());
+ if (!typeArgsAreCanonical || !protocolsSorted || !baseType.isCanonical()) {
+ // Determine the canonical type arguments.
+ ArrayRef<QualType> canonTypeArgs;
+ SmallVector<QualType, 4> canonTypeArgsVec;
+ if (!typeArgsAreCanonical) {
+ canonTypeArgsVec.reserve(effectiveTypeArgs.size());
+ for (auto typeArg : effectiveTypeArgs)
+ canonTypeArgsVec.push_back(getCanonicalType(typeArg));
+ canonTypeArgs = canonTypeArgsVec;
} else {
- Canonical = getObjCObjectType(getCanonicalType(BaseType),
- Protocols, NumProtocols);
+ canonTypeArgs = effectiveTypeArgs;
}
+ ArrayRef<ObjCProtocolDecl *> canonProtocols;
+ SmallVector<ObjCProtocolDecl*, 8> canonProtocolsVec;
+ if (!protocolsSorted) {
+ canonProtocolsVec.insert(canonProtocolsVec.begin(),
+ protocols.begin(),
+ protocols.end());
+ unsigned uniqueCount = protocols.size();
+ SortAndUniqueProtocols(&canonProtocolsVec[0], uniqueCount);
+ canonProtocols = llvm::makeArrayRef(&canonProtocolsVec[0], uniqueCount);
+ } else {
+ canonProtocols = protocols;
+ }
+
+ canonical = getObjCObjectType(getCanonicalType(baseType), canonTypeArgs,
+ canonProtocols, isKindOf);
+
// Regenerate InsertPos.
ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos);
}
- unsigned Size = sizeof(ObjCObjectTypeImpl);
- Size += NumProtocols * sizeof(ObjCProtocolDecl *);
- void *Mem = Allocate(Size, TypeAlignment);
+ unsigned size = sizeof(ObjCObjectTypeImpl);
+ size += typeArgs.size() * sizeof(QualType);
+ size += protocols.size() * sizeof(ObjCProtocolDecl *);
+ void *mem = Allocate(size, TypeAlignment);
ObjCObjectTypeImpl *T =
- new (Mem) ObjCObjectTypeImpl(Canonical, BaseType, Protocols, NumProtocols);
+ new (mem) ObjCObjectTypeImpl(canonical, baseType, typeArgs, protocols,
+ isKindOf);
Types.push_back(T);
ObjCObjectTypes.InsertNode(T, InsertPos);
@@ -5623,13 +5663,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
case Type::ObjCInterface: {
// Ignore protocol qualifiers when mangling at this level.
- T = T->castAs<ObjCObjectType>()->getBaseType();
-
- // The assumption seems to be that this assert will succeed
- // because nested levels will have filtered out 'id' and 'Class'.
- const ObjCInterfaceType *OIT = T->castAs<ObjCInterfaceType>();
// @encode(class_name)
- ObjCInterfaceDecl *OI = OIT->getDecl();
+ ObjCInterfaceDecl *OI = T->castAs<ObjCObjectType>()->getInterface();
S += '{';
S += OI->getObjCRuntimeNameAsString();
S += '=';
@@ -5921,7 +5956,7 @@ void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
TypedefDecl *ASTContext::getObjCIdDecl() const {
if (!ObjCIdDecl) {
- QualType T = getObjCObjectType(ObjCBuiltinIdTy, nullptr, 0);
+ QualType T = getObjCObjectType(ObjCBuiltinIdTy, { }, { });
T = getObjCObjectPointerType(T);
ObjCIdDecl = buildImplicitTypedef(T, "id");
}
@@ -5938,7 +5973,7 @@ TypedefDecl *ASTContext::getObjCSelDecl() const {
TypedefDecl *ASTContext::getObjCClassDecl() const {
if (!ObjCClassDecl) {
- QualType T = getObjCObjectType(ObjCBuiltinClassTy, nullptr, 0);
+ QualType T = getObjCObjectType(ObjCBuiltinClassTy, { }, { });
T = getObjCObjectPointerType(T);
ObjCClassDecl = buildImplicitTypedef(T, "Class");
}
@@ -5951,6 +5986,7 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const {
= ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(),
&Idents.get("Protocol"),
+ /*typeParamList=*/nullptr,
/*PrevDecl=*/nullptr,
SourceLocation(), true);
}
@@ -6743,18 +6779,36 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
RHS->isObjCUnqualifiedIdOrClass())
return true;
- if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId())
- return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
- QualType(RHSOPT,0),
- false);
+ // Function object that propagates a successful result or handles
+ // __kindof types.
+ auto finish = [&](bool succeeded) -> bool {
+ if (succeeded)
+ return true;
+
+ if (!RHS->isKindOfType())
+ return false;
+
+ // Strip off __kindof and protocol qualifiers, then check whether
+ // we can assign the other way.
+ return canAssignObjCInterfaces(RHSOPT->stripObjCKindOfTypeAndQuals(*this),
+ LHSOPT->stripObjCKindOfTypeAndQuals(*this));
+ };
+
+ if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId()) {
+ return finish(ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
+ QualType(RHSOPT,0),
+ false));
+ }
- if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass())
- return ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
- QualType(RHSOPT,0));
+ if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass()) {
+ return finish(ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
+ QualType(RHSOPT,0)));
+ }
// If we have 2 user-defined types, fall into that path.
- if (LHS->getInterface() && RHS->getInterface())
- return canAssignObjCInterfaces(LHS, RHS);
+ if (LHS->getInterface() && RHS->getInterface()) {
+ return finish(canAssignObjCInterfaces(LHS, RHS));
+ }
return false;
}
@@ -6768,26 +6822,46 @@ bool ASTContext::canAssignObjCInterfacesInBlockPointer(
const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT,
bool BlockReturnType) {
+
+ // Function object that propagates a successful result or handles
+ // __kindof types.
+ auto finish = [&](bool succeeded) -> bool {
+ if (succeeded)
+ return true;
+
+ const ObjCObjectPointerType *Expected = BlockReturnType ? RHSOPT : LHSOPT;
+ if (!Expected->isKindOfType())
+ return false;
+
+ // Strip off __kindof and protocol qualifiers, then check whether
+ // we can assign the other way.
+ return canAssignObjCInterfacesInBlockPointer(
+ RHSOPT->stripObjCKindOfTypeAndQuals(*this),
+ LHSOPT->stripObjCKindOfTypeAndQuals(*this),
+ BlockReturnType);
+ };
+
if (RHSOPT->isObjCBuiltinType() || LHSOPT->isObjCIdType())
return true;
if (LHSOPT->isObjCBuiltinType()) {
- return RHSOPT->isObjCBuiltinType() || RHSOPT->isObjCQualifiedIdType();
+ return finish(RHSOPT->isObjCBuiltinType() ||
+ RHSOPT->isObjCQualifiedIdType());
}
if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
- return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
- QualType(RHSOPT,0),
- false);
+ return finish(ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
+ QualType(RHSOPT,0),
+ false));
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
if (LHS && RHS) { // We have 2 user-defined types.
if (LHS != RHS) {
if (LHS->getDecl()->isSuperClassOf(RHS->getDecl()))
- return BlockReturnType;
+ return finish(BlockReturnType);
if (RHS->getDecl()->isSuperClassOf(LHS->getDecl()))
- return !BlockReturnType;
+ return finish(!BlockReturnType);
}
else
return true;
@@ -6795,78 +6869,253 @@ bool ASTContext::canAssignObjCInterfacesInBlockPointer(
return false;
}
+/// Comparison routine for Objective-C protocols to be used with
+/// llvm::array_pod_sort.
+static int compareObjCProtocolsByName(ObjCProtocolDecl * const *lhs,
+ ObjCProtocolDecl * const *rhs) {
+ return (*lhs)->getName().compare((*rhs)->getName());
+
+}
+
/// getIntersectionOfProtocols - This routine finds the intersection of set
-/// of protocols inherited from two distinct objective-c pointer objects.
+/// of protocols inherited from two distinct objective-c pointer objects with
+/// the given common base.
/// It is used to build composite qualifier list of the composite type of
/// the conditional expression involving two objective-c pointer objects.
static
void getIntersectionOfProtocols(ASTContext &Context,
+ const ObjCInterfaceDecl *CommonBase,
const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT,
- SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
+ SmallVectorImpl<ObjCProtocolDecl *> &IntersectionSet) {
const ObjCObjectType* LHS = LHSOPT->getObjectType();
const ObjCObjectType* RHS = RHSOPT->getObjectType();
assert(LHS->getInterface() && "LHS must have an interface base");
assert(RHS->getInterface() && "RHS must have an interface base");
-
- llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet;
- unsigned LHSNumProtocols = LHS->getNumProtocols();
- if (LHSNumProtocols > 0)
- InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
- else {
- llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
- Context.CollectInheritedProtocols(LHS->getInterface(),
- LHSInheritedProtocols);
- InheritedProtocolSet.insert(LHSInheritedProtocols.begin(),
- LHSInheritedProtocols.end());
+
+ // Add all of the protocols for the LHS.
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSProtocolSet;
+
+ // Start with the protocol qualifiers.
+ for (auto proto : LHS->quals()) {
+ Context.CollectInheritedProtocols(proto, LHSProtocolSet);
}
-
- unsigned RHSNumProtocols = RHS->getNumProtocols();
- if (RHSNumProtocols > 0) {
- ObjCProtocolDecl **RHSProtocols =
- const_cast<ObjCProtocolDecl **>(RHS->qual_begin());
- for (unsigned i = 0; i < RHSNumProtocols; ++i)
- if (InheritedProtocolSet.count(RHSProtocols[i]))
- IntersectionOfProtocols.push_back(RHSProtocols[i]);
- } else {
- llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
- Context.CollectInheritedProtocols(RHS->getInterface(),
- RHSInheritedProtocols);
- for (ObjCProtocolDecl *ProtDecl : RHSInheritedProtocols)
- if (InheritedProtocolSet.count(ProtDecl))
- IntersectionOfProtocols.push_back(ProtDecl);
+
+ // Also add the protocols associated with the LHS interface.
+ Context.CollectInheritedProtocols(LHS->getInterface(), LHSProtocolSet);
+
+ // Add all of the protocls for the RHS.
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSProtocolSet;
+
+ // Start with the protocol qualifiers.
+ for (auto proto : RHS->quals()) {
+ Context.CollectInheritedProtocols(proto, RHSProtocolSet);
+ }
+
+ // Also add the protocols associated with the RHS interface.
+ Context.CollectInheritedProtocols(RHS->getInterface(), RHSProtocolSet);
+
+ // Compute the intersection of the collected protocol sets.
+ for (auto proto : LHSProtocolSet) {
+ if (RHSProtocolSet.count(proto))
+ IntersectionSet.push_back(proto);
}
+
+ // Compute the set of protocols that is implied by either the common type or
+ // the protocols within the intersection.
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ImpliedProtocols;
+ Context.CollectInheritedProtocols(CommonBase, ImpliedProtocols);
+
+ // Remove any implied protocols from the list of inherited protocols.
+ if (!ImpliedProtocols.empty()) {
+ IntersectionSet.erase(
+ std::remove_if(IntersectionSet.begin(),
+ IntersectionSet.end(),
+ [&](ObjCProtocolDecl *proto) -> bool {
+ return ImpliedProtocols.count(proto) > 0;
+ }),
+ IntersectionSet.end());
+ }
+
+ // Sort the remaining protocols by name.
+ llvm::array_pod_sort(IntersectionSet.begin(), IntersectionSet.end(),
+ compareObjCProtocolsByName);
+}
+
+/// Determine whether the first type is a subtype of the second.
+static bool canAssignObjCObjectTypes(ASTContext &ctx, QualType lhs,
+ QualType rhs) {
+ // Common case: two object pointers.
+ const ObjCObjectPointerType *lhsOPT = lhs->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
+ if (lhsOPT && rhsOPT)
+ return ctx.canAssignObjCInterfaces(lhsOPT, rhsOPT);
+
+ // Two block pointers.
+ const BlockPointerType *lhsBlock = lhs->getAs<BlockPointerType>();
+ const BlockPointerType *rhsBlock = rhs->getAs<BlockPointerType>();
+ if (lhsBlock && rhsBlock)
+ return ctx.typesAreBlockPointerCompatible(lhs, rhs);
+
+ // If either is an unqualified 'id' and the other is a block, it's
+ // acceptable.
+ if ((lhsOPT && lhsOPT->isObjCIdType() && rhsBlock) ||
+ (rhsOPT && rhsOPT->isObjCIdType() && lhsBlock))
+ return true;
+
+ return false;
+}
+
+// Check that the given Objective-C type argument lists are equivalent.
+static bool sameObjCTypeArgs(ASTContext &ctx,
+ const ObjCInterfaceDecl *iface,
+ ArrayRef<QualType> lhsArgs,
+ ArrayRef<QualType> rhsArgs,
+ bool stripKindOf) {
+ if (lhsArgs.size() != rhsArgs.size())
+ return false;
+
+ ObjCTypeParamList *typeParams = iface->getTypeParamList();
+ for (unsigned i = 0, n = lhsArgs.size(); i != n; ++i) {
+ if (ctx.hasSameType(lhsArgs[i], rhsArgs[i]))
+ continue;
+
+ switch (typeParams->begin()[i]->getVariance()) {
+ case ObjCTypeParamVariance::Invariant:
+ if (!stripKindOf ||
+ !ctx.hasSameType(lhsArgs[i].stripObjCKindOfType(ctx),
+ rhsArgs[i].stripObjCKindOfType(ctx))) {
+ return false;
+ }
+ break;
+
+ case ObjCTypeParamVariance::Covariant:
+ if (!canAssignObjCObjectTypes(ctx, lhsArgs[i], rhsArgs[i]))
+ return false;
+ break;
+
+ case ObjCTypeParamVariance::Contravariant:
+ if (!canAssignObjCObjectTypes(ctx, rhsArgs[i], lhsArgs[i]))
+ return false;
+ break;
+ }
+ }
+
+ return true;
}
-/// areCommonBaseCompatible - Returns common base class of the two classes if
-/// one found. Note that this is O'2 algorithm. But it will be called as the
-/// last type comparison in a ?-exp of ObjC pointer types before a
-/// warning is issued. So, its invokation is extremely rare.
QualType ASTContext::areCommonBaseCompatible(
- const ObjCObjectPointerType *Lptr,
- const ObjCObjectPointerType *Rptr) {
+ const ObjCObjectPointerType *Lptr,
+ const ObjCObjectPointerType *Rptr) {
const ObjCObjectType *LHS = Lptr->getObjectType();
const ObjCObjectType *RHS = Rptr->getObjectType();
const ObjCInterfaceDecl* LDecl = LHS->getInterface();
const ObjCInterfaceDecl* RDecl = RHS->getInterface();
- if (!LDecl || !RDecl || (declaresSameEntity(LDecl, RDecl)))
+
+ if (!LDecl || !RDecl)
return QualType();
-
- do {
- LHS = cast<ObjCInterfaceType>(getObjCInterfaceType(LDecl));
- if (canAssignObjCInterfaces(LHS, RHS)) {
+
+ // Follow the left-hand side up the class hierarchy until we either hit a
+ // root or find the RHS. Record the ancestors in case we don't find it.
+ llvm::SmallDenseMap<const ObjCInterfaceDecl *, const ObjCObjectType *, 4>
+ LHSAncestors;
+ while (true) {
+ // Record this ancestor. We'll need this if the common type isn't in the
+ // path from the LHS to the root.
+ LHSAncestors[LHS->getInterface()->getCanonicalDecl()] = LHS;
+
+ if (declaresSameEntity(LHS->getInterface(), RDecl)) {
+ // Get the type arguments.
+ ArrayRef<QualType> LHSTypeArgs = LHS->getTypeArgsAsWritten();
+ bool anyChanges = false;
+ if (LHS->isSpecialized() && RHS->isSpecialized()) {
+ // Both have type arguments, compare them.
+ if (!sameObjCTypeArgs(*this, LHS->getInterface(),
+ LHS->getTypeArgs(), RHS->getTypeArgs(),
+ /*stripKindOf=*/true))
+ return QualType();
+ } else if (LHS->isSpecialized() != RHS->isSpecialized()) {
+ // If only one has type arguments, the result will not have type
+ // arguments.
+ LHSTypeArgs = { };
+ anyChanges = true;
+ }
+
+ // Compute the intersection of protocols.
SmallVector<ObjCProtocolDecl *, 8> Protocols;
- getIntersectionOfProtocols(*this, Lptr, Rptr, Protocols);
+ getIntersectionOfProtocols(*this, LHS->getInterface(), Lptr, Rptr,
+ Protocols);
+ if (!Protocols.empty())
+ anyChanges = true;
+
+ // If anything in the LHS will have changed, build a new result type.
+ if (anyChanges) {
+ QualType Result = getObjCInterfaceType(LHS->getInterface());
+ Result = getObjCObjectType(Result, LHSTypeArgs, Protocols,
+ LHS->isKindOfType());
+ return getObjCObjectPointerType(Result);
+ }
+
+ return getObjCObjectPointerType(QualType(LHS, 0));
+ }
+
+ // Find the superclass.
+ QualType LHSSuperType = LHS->getSuperClassType();
+ if (LHSSuperType.isNull())
+ break;
- QualType Result = QualType(LHS, 0);
+ LHS = LHSSuperType->castAs<ObjCObjectType>();
+ }
+
+ // We didn't find anything by following the LHS to its root; now check
+ // the RHS against the cached set of ancestors.
+ while (true) {
+ auto KnownLHS = LHSAncestors.find(RHS->getInterface()->getCanonicalDecl());
+ if (KnownLHS != LHSAncestors.end()) {
+ LHS = KnownLHS->second;
+
+ // Get the type arguments.
+ ArrayRef<QualType> RHSTypeArgs = RHS->getTypeArgsAsWritten();
+ bool anyChanges = false;
+ if (LHS->isSpecialized() && RHS->isSpecialized()) {
+ // Both have type arguments, compare them.
+ if (!sameObjCTypeArgs(*this, LHS->getInterface(),
+ LHS->getTypeArgs(), RHS->getTypeArgs(),
+ /*stripKindOf=*/true))
+ return QualType();
+ } else if (LHS->isSpecialized() != RHS->isSpecialized()) {
+ // If only one has type arguments, the result will not have type
+ // arguments.
+ RHSTypeArgs = { };
+ anyChanges = true;
+ }
+
+ // Compute the intersection of protocols.
+ SmallVector<ObjCProtocolDecl *, 8> Protocols;
+ getIntersectionOfProtocols(*this, RHS->getInterface(), Lptr, Rptr,
+ Protocols);
if (!Protocols.empty())
- Result = getObjCObjectType(Result, Protocols.data(), Protocols.size());
- Result = getObjCObjectPointerType(Result);
- return Result;
+ anyChanges = true;
+
+ if (anyChanges) {
+ QualType Result = getObjCInterfaceType(RHS->getInterface());
+ Result = getObjCObjectType(Result, RHSTypeArgs, Protocols,
+ RHS->isKindOfType());
+ return getObjCObjectPointerType(Result);
+ }
+
+ return getObjCObjectPointerType(QualType(RHS, 0));
}
- } while ((LDecl = LDecl->getSuperClass()));
-
+
+ // Find the superclass of the RHS.
+ QualType RHSSuperType = RHS->getSuperClassType();
+ if (RHSSuperType.isNull())
+ break;
+
+ RHS = RHSSuperType->castAs<ObjCObjectType>();
+ }
+
return QualType();
}
@@ -6877,21 +7126,15 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
// Verify that the base decls are compatible: the RHS must be a subclass of
// the LHS.
- if (!LHS->getInterface()->isSuperClassOf(RHS->getInterface()))
+ ObjCInterfaceDecl *LHSInterface = LHS->getInterface();
+ bool IsSuperClass = LHSInterface->isSuperClassOf(RHS->getInterface());
+ if (!IsSuperClass)
return false;
- // RHS must have a superset of the protocols in the LHS. If the LHS is not
- // protocol qualified at all, then we are good.
- if (LHS->getNumProtocols() == 0)
- return true;
-
- // Okay, we know the LHS has protocol qualifiers. But RHS may or may not.
- // More detailed analysis is required.
- // OK, if LHS is same or a superclass of RHS *and*
- // this LHS, or as RHS's super class is assignment compatible with LHS.
- bool IsSuperClass =
- LHS->getInterface()->isSuperClassOf(RHS->getInterface());
- if (IsSuperClass) {
+ // If the LHS has protocol qualifiers, determine whether all of them are
+ // satisfied by the RHS (i.e., the RHS has a superset of the protocols in the
+ // LHS).
+ if (LHS->getNumProtocols() > 0) {
// OK if conversion of LHS to SuperClass results in narrowing of types
// ; i.e., SuperClass may implement at least one of the protocols
// in LHS's protocol list. Example, SuperObj<P1> = lhs<P1,P2> is ok.
@@ -6901,7 +7144,7 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
// Also, if RHS has explicit quelifiers, include them for comparing with LHS's
// qualifiers.
for (auto *RHSPI : RHS->quals())
- SuperClassInheritedProtocols.insert(RHSPI->getCanonicalDecl());
+ CollectInheritedProtocols(RHSPI, SuperClassInheritedProtocols);
// If there is no protocols associated with RHS, it is not a match.
if (SuperClassInheritedProtocols.empty())
return false;
@@ -6916,9 +7159,26 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
if (!SuperImplementsProtocol)
return false;
}
- return true;
}
- return false;
+
+ // If the LHS is specialized, we may need to check type arguments.
+ if (LHS->isSpecialized()) {
+ // Follow the superclass chain until we've matched the LHS class in the
+ // hierarchy. This substitutes type arguments through.
+ const ObjCObjectType *RHSSuper = RHS;
+ while (!declaresSameEntity(RHSSuper->getInterface(), LHSInterface))
+ RHSSuper = RHSSuper->getSuperClassType()->castAs<ObjCObjectType>();
+
+ // If the RHS is specializd, compare type arguments.
+ if (RHSSuper->isSpecialized() &&
+ !sameObjCTypeArgs(*this, LHS->getInterface(),
+ LHS->getTypeArgs(), RHSSuper->getTypeArgs(),
+ /*stripKindOf=*/true)) {
+ return false;
+ }
+ }
+
+ return true;
}
bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 000588face96..dddaa5af6fb0 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -125,12 +125,23 @@ break; \
if (const PointerType *Ty = QT->getAs<PointerType>()) {
QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(),
ShouldAKA));
+ } else if (const auto *Ty = QT->getAs<ObjCObjectPointerType>()) {
+ QT = Context.getObjCObjectPointerType(Desugar(Context, Ty->getPointeeType(),
+ ShouldAKA));
} else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {
QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(),
ShouldAKA));
} else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {
QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(),
ShouldAKA));
+ } else if (const auto *Ty = QT->getAs<ObjCObjectType>()) {
+ if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {
+ QualType BaseType = Desugar(Context, Ty->getBaseType(), ShouldAKA);
+ QT = Context.getObjCObjectType(BaseType, Ty->getTypeArgsAsWritten(),
+ llvm::makeArrayRef(Ty->qual_begin(),
+ Ty->getNumProtocols()),
+ Ty->isKindOfTypeAsWritten());
+ }
}
return QC.apply(Context, QT);
@@ -181,8 +192,8 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
if (CompareCanTy == CanTy)
continue; // Same canonical types
std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());
- bool aka;
- QualType CompareDesugar = Desugar(Context, CompareTy, aka);
+ bool ShouldAKA = false;
+ QualType CompareDesugar = Desugar(Context, CompareTy, ShouldAKA);
std::string CompareDesugarStr =
CompareDesugar.getAsString(Context.getPrintingPolicy());
if (CompareS != S && CompareDesugarStr != S)
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 90da4167197a..c95922b141e0 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -240,6 +240,9 @@ namespace {
void dumpTemplateArgument(const TemplateArgument &A,
SourceRange R = SourceRange());
+ // Objective-C utilities.
+ void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams);
+
// Types
void VisitComplexType(const ComplexType *T) {
dumpTypeAsChild(T->getElementType());
@@ -463,6 +466,7 @@ namespace {
// ObjC Decls
void VisitObjCIvarDecl(const ObjCIvarDecl *D);
void VisitObjCMethodDecl(const ObjCMethodDecl *D);
+ void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D);
void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
@@ -955,6 +959,18 @@ void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) {
}
//===----------------------------------------------------------------------===//
+// Objective-C Utilities
+//===----------------------------------------------------------------------===//
+void ASTDumper::dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) {
+ if (!typeParams)
+ return;
+
+ for (auto typeParam : *typeParams) {
+ dumpDecl(typeParam);
+ }
+}
+
+//===----------------------------------------------------------------------===//
// Decl dumping methods.
//===----------------------------------------------------------------------===//
@@ -1457,9 +1473,30 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
dumpStmt(D->getBody());
}
+void ASTDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
+ dumpName(D);
+ switch (D->getVariance()) {
+ case ObjCTypeParamVariance::Invariant:
+ break;
+
+ case ObjCTypeParamVariance::Covariant:
+ OS << " covariant";
+ break;
+
+ case ObjCTypeParamVariance::Contravariant:
+ OS << " contravariant";
+ break;
+ }
+
+ if (D->hasExplicitBound())
+ OS << " bounded";
+ dumpType(D->getUnderlyingType());
+}
+
void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
dumpName(D);
dumpDeclRef(D->getClassInterface());
+ dumpObjCTypeParamList(D->getTypeParamList());
dumpDeclRef(D->getImplementation());
for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(),
E = D->protocol_end();
@@ -1482,6 +1519,7 @@ void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
dumpName(D);
+ dumpObjCTypeParamList(D->getTypeParamListAsWritten());
dumpDeclRef(D->getSuperClass(), "super");
dumpDeclRef(D->getImplementation());
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 76e4e1191501..35c0f690db82 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -150,9 +150,12 @@ namespace clang {
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);
+
+ ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list);
Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
@@ -1841,6 +1844,15 @@ QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
if (ToBaseType.isNull())
return QualType();
+ SmallVector<QualType, 4> TypeArgs;
+ for (auto TypeArg : T->getTypeArgsAsWritten()) {
+ QualType ImportedTypeArg = Importer.Import(TypeArg);
+ if (ImportedTypeArg.isNull())
+ return QualType();
+
+ TypeArgs.push_back(ImportedTypeArg);
+ }
+
SmallVector<ObjCProtocolDecl *, 4> Protocols;
for (auto *P : T->quals()) {
ObjCProtocolDecl *Protocol
@@ -1850,9 +1862,9 @@ QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
Protocols.push_back(Protocol);
}
- return Importer.getToContext().getObjCObjectType(ToBaseType,
- Protocols.data(),
- Protocols.size());
+ return Importer.getToContext().getObjCObjectType(ToBaseType, TypeArgs,
+ Protocols,
+ T->isKindOfTypeAsWritten());
}
QualType
@@ -3423,6 +3435,35 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
return ToMethod;
}
+Decl *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 (ToD)
+ return ToD;
+
+ TypeSourceInfo *BoundInfo = Importer.Import(D->getTypeSourceInfo());
+ if (!BoundInfo)
+ return nullptr;
+
+ ObjCTypeParamDecl *Result = ObjCTypeParamDecl::Create(
+ Importer.getToContext(), DC,
+ D->getVariance(),
+ Importer.Import(D->getVarianceLoc()),
+ D->getIndex(),
+ Importer.Import(D->getLocation()),
+ Name.getAsIdentifierInfo(),
+ Importer.Import(D->getColonLoc()),
+ BoundInfo);
+ Importer.Imported(D, Result);
+ Result->setLexicalDeclContext(LexicalDC);
+ return Result;
+}
+
Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
// Import the major distinguishing characteristics of a category.
DeclContext *DC, *LexicalDC;
@@ -3450,11 +3491,16 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
Importer.Import(D->getCategoryNameLoc()),
Name.getAsIdentifierInfo(),
ToInterface,
+ /*TypeParamList=*/nullptr,
Importer.Import(D->getIvarLBraceLoc()),
Importer.Import(D->getIvarRBraceLoc()));
ToCategory->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToCategory);
Importer.Imported(D, ToCategory);
+ // Import the type parameter list after calling Imported, to avoid
+ // loops when bringing in their DeclContext.
+ ToCategory->setTypeParamList(ImportObjCTypeParamList(
+ D->getTypeParamList()));
// Import protocols
SmallVector<ObjCProtocolDecl *, 4> Protocols;
@@ -3663,13 +3709,11 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
// If this class has a superclass, import it.
if (From->getSuperClass()) {
- ObjCInterfaceDecl *Super = cast_or_null<ObjCInterfaceDecl>(
- Importer.Import(From->getSuperClass()));
- if (!Super)
+ TypeSourceInfo *SuperTInfo = Importer.Import(From->getSuperClassTInfo());
+ if (!SuperTInfo)
return true;
-
- To->setSuperClass(Super);
- To->setSuperClassLoc(Importer.Import(From->getSuperClassLoc()));
+
+ To->setSuperClass(SuperTInfo);
}
// Import protocols
@@ -3716,6 +3760,27 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
return false;
}
+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);
+ }
+
+ return ObjCTypeParamList::create(Importer.getToContext(),
+ Importer.Import(list->getLAngleLoc()),
+ toTypeParams,
+ Importer.Import(list->getRAngleLoc()));
+}
+
Decl *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
@@ -3756,13 +3821,18 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
if (!ToIface) {
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getAtStartLoc()),
- Name.getAsIdentifierInfo(),
+ Name.getAsIdentifierInfo(),
+ /*TypeParamList=*/nullptr,
/*PrevDecl=*/nullptr, Loc,
D->isImplicitInterfaceDecl());
ToIface->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToIface);
}
Importer.Imported(D, ToIface);
+ // Import the type parameter list after calling Imported, to avoid
+ // loops when bringing in their DeclContext.
+ ToIface->setTypeParamList(ImportObjCTypeParamList(
+ D->getTypeParamListAsWritten()));
if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface))
return nullptr;
@@ -5313,7 +5383,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
return nullptr;
return ToContext.getTrivialTypeSourceInfo(T,
- FromTSI->getTypeLoc().getLocStart());
+ Import(FromTSI->getTypeLoc().getLocStart()));
}
Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d9a3389c58f3..ea4b2f517cd0 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1803,15 +1803,19 @@ void VarDecl::setStorageClass(StorageClass SC) {
VarDecl::TLSKind VarDecl::getTLSKind() const {
switch (VarDeclBits.TSCSpec) {
case TSCS_unspecified:
- if (!hasAttr<ThreadAttr>())
+ if (!hasAttr<ThreadAttr>() &&
+ !(getASTContext().getLangOpts().OpenMPUseTLS &&
+ getASTContext().getTargetInfo().isTLSSupported() &&
+ hasAttr<OMPThreadPrivateDeclAttr>()))
return TLS_None;
- return getASTContext().getLangOpts().isCompatibleWithMSVC(
- LangOptions::MSVC2015)
+ return ((getASTContext().getLangOpts().isCompatibleWithMSVC(
+ LangOptions::MSVC2015)) ||
+ hasAttr<OMPThreadPrivateDeclAttr>())
? TLS_Dynamic
: TLS_Static;
case TSCS___thread: // Fall through.
case TSCS__Thread_local:
- return TLS_Static;
+ return TLS_Static;
case TSCS_thread_local:
return TLS_Dynamic;
}
@@ -2712,7 +2716,7 @@ bool FunctionDecl::isMSExternInline() const {
for (const FunctionDecl *FD = getMostRecentDecl(); FD;
FD = FD->getPreviousDecl())
- if (FD->getStorageClass() == SC_Extern)
+ if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
return true;
return false;
@@ -2724,7 +2728,7 @@ static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) {
for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD;
FD = FD->getPreviousDecl())
- if (FD->getStorageClass() == SC_Extern)
+ if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
return false;
return true;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index d20451d1badc..4fcec53d6eb9 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -561,6 +561,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case TypeAliasTemplate:
case UnresolvedUsingTypename:
case TemplateTypeParm:
+ case ObjCTypeParam:
return IDNS_Ordinary | IDNS_Type;
case UsingShadow:
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index b00b8a0ea9cc..d905fcf13a45 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -1272,7 +1272,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
break;
CTD = NewCTD;
}
- return CTD->getTemplatedDecl();
+ return CTD->getTemplatedDecl()->getDefinition();
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
@@ -1281,7 +1281,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
break;
CTPSD = NewCTPSD;
}
- return CTPSD;
+ return CTPSD->getDefinition();
}
}
@@ -1290,7 +1290,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
const CXXRecordDecl *RD = this;
while (auto *NewRD = RD->getInstantiatedFromMemberClass())
RD = NewRD;
- return RD;
+ return RD->getDefinition();
}
}
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index a1600cb11014..280c412ae8ff 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -239,6 +239,62 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
void ObjCInterfaceDecl::anchor() { }
+ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const {
+ // If this particular declaration has a type parameter list, return it.
+ if (ObjCTypeParamList *written = getTypeParamListAsWritten())
+ return written;
+
+ // If there is a definition, return its type parameter list.
+ if (const ObjCInterfaceDecl *def = getDefinition())
+ return def->getTypeParamListAsWritten();
+
+ // Otherwise, look at previous declarations to determine whether any
+ // of them has a type parameter list, skipping over those
+ // declarations that do not.
+ for (auto decl = getMostRecentDecl(); decl; decl = decl->getPreviousDecl()) {
+ if (ObjCTypeParamList *written = decl->getTypeParamListAsWritten())
+ return written;
+ }
+
+ return nullptr;
+}
+
+void ObjCInterfaceDecl::setTypeParamList(ObjCTypeParamList *TPL) {
+ TypeParamList = TPL;
+ if (!TPL)
+ return;
+ // Set the declaration context of each of the type parameters.
+ for (auto typeParam : *TypeParamList)
+ typeParam->setDeclContext(this);
+}
+
+ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return nullptr;
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ if (const ObjCObjectType *superType = getSuperClassType()) {
+ if (ObjCInterfaceDecl *superDecl = superType->getInterface()) {
+ if (ObjCInterfaceDecl *superDef = superDecl->getDefinition())
+ return superDef;
+
+ return superDecl;
+ }
+ }
+
+ return nullptr;
+}
+
+SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
+ if (TypeSourceInfo *superTInfo = getSuperClassTInfo())
+ return superTInfo->getTypeLoc().getLocStart();
+
+ return SourceLocation();
+}
+
/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
/// with name 'PropertyId' in the primary class; including those in protocols
/// (direct or indirect) used by the primary class.
@@ -889,9 +945,13 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
return family;
}
-void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
- const ObjCInterfaceDecl *OID) {
+QualType ObjCMethodDecl::getSelfType(ASTContext &Context,
+ const ObjCInterfaceDecl *OID,
+ bool &selfIsPseudoStrong,
+ bool &selfIsConsumed) {
QualType selfTy;
+ selfIsPseudoStrong = false;
+ selfIsConsumed = false;
if (isInstanceMethod()) {
// There may be no interface context due to error in declaration
// of the interface (which has been reported). Recover gracefully.
@@ -904,9 +964,6 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
} else // we have a factory method.
selfTy = Context.getObjCClassType();
- bool selfIsPseudoStrong = false;
- bool selfIsConsumed = false;
-
if (Context.getLangOpts().ObjCAutoRefCount) {
if (isInstanceMethod()) {
selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
@@ -930,7 +987,14 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
selfIsPseudoStrong = true;
}
}
+ return selfTy;
+}
+void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
+ const ObjCInterfaceDecl *OID) {
+ bool selfIsPseudoStrong, selfIsConsumed;
+ QualType selfTy =
+ getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed);
ImplicitParamDecl *self
= ImplicitParamDecl::Create(Context, this, SourceLocation(),
&Context.Idents.get("self"), selfTy);
@@ -966,6 +1030,20 @@ SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const {
return SourceRange();
}
+QualType ObjCMethodDecl::getSendResultType() const {
+ ASTContext &Ctx = getASTContext();
+ return getReturnType().getNonLValueExprType(Ctx)
+ .substObjCTypeArgs(Ctx, {}, ObjCSubstitutionContext::Result);
+}
+
+QualType ObjCMethodDecl::getSendResultType(QualType receiverType) const {
+ // FIXME: Handle related result types here.
+
+ return getReturnType().getNonLValueExprType(getASTContext())
+ .substObjCMemberType(receiverType, getDeclContext(),
+ ObjCSubstitutionContext::Result);
+}
+
static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
const ObjCMethodDecl *Method,
SmallVectorImpl<const ObjCMethodDecl *> &Methods,
@@ -1137,6 +1215,81 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
}
//===----------------------------------------------------------------------===//
+// ObjCTypeParamDecl
+//===----------------------------------------------------------------------===//
+
+void ObjCTypeParamDecl::anchor() { }
+
+ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
+ ObjCTypeParamVariance variance,
+ SourceLocation varianceLoc,
+ unsigned index,
+ SourceLocation nameLoc,
+ IdentifierInfo *name,
+ SourceLocation colonLoc,
+ TypeSourceInfo *boundInfo) {
+ return new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
+ nameLoc, name, colonLoc, boundInfo);
+}
+
+ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
+ unsigned ID) {
+ return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr,
+ ObjCTypeParamVariance::Invariant,
+ SourceLocation(), 0, SourceLocation(),
+ nullptr, SourceLocation(), nullptr);
+}
+
+SourceRange ObjCTypeParamDecl::getSourceRange() const {
+ SourceLocation startLoc = VarianceLoc;
+ if (startLoc.isInvalid())
+ startLoc = getLocation();
+
+ if (hasExplicitBound()) {
+ return SourceRange(startLoc,
+ getTypeSourceInfo()->getTypeLoc().getEndLoc());
+ }
+
+ return SourceRange(startLoc);
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCTypeParamList
+//===----------------------------------------------------------------------===//
+ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc,
+ ArrayRef<ObjCTypeParamDecl *> typeParams,
+ SourceLocation rAngleLoc)
+ : NumParams(typeParams.size())
+{
+ Brackets.Begin = lAngleLoc.getRawEncoding();
+ Brackets.End = rAngleLoc.getRawEncoding();
+ std::copy(typeParams.begin(), typeParams.end(), begin());
+}
+
+
+ObjCTypeParamList *ObjCTypeParamList::create(
+ ASTContext &ctx,
+ SourceLocation lAngleLoc,
+ ArrayRef<ObjCTypeParamDecl *> typeParams,
+ SourceLocation rAngleLoc) {
+ unsigned size = sizeof(ObjCTypeParamList)
+ + sizeof(ObjCTypeParamDecl *) * typeParams.size();
+ static_assert(llvm::AlignOf<ObjCTypeParamList>::Alignment >=
+ llvm::AlignOf<ObjCTypeParamDecl *>::Alignment,
+ "type parameter list needs greater alignment");
+ unsigned align = llvm::alignOf<ObjCTypeParamList>();
+ void *mem = ctx.Allocate(size, align);
+ return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc);
+}
+
+void ObjCTypeParamList::gatherDefaultTypeArgs(
+ SmallVectorImpl<QualType> &typeArgs) const {
+ typeArgs.reserve(size());
+ for (auto typeParam : *this)
+ typeArgs.push_back(typeParam->getUnderlyingType());
+}
+
+//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
@@ -1144,11 +1297,13 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
+ ObjCTypeParamList *typeParamList,
ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc,
bool isInternal){
ObjCInterfaceDecl *Result = new (C, DC)
- ObjCInterfaceDecl(C, DC, atLoc, Id, ClassLoc, PrevDecl, isInternal);
+ ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl,
+ isInternal);
Result->Data.setInt(!C.getLangOpts().Modules);
C.getObjCInterfaceType(Result, PrevDecl);
return Result;
@@ -1159,6 +1314,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
ObjCInterfaceDecl *Result = new (C, ID) ObjCInterfaceDecl(C, nullptr,
SourceLocation(),
nullptr,
+ nullptr,
SourceLocation(),
nullptr, false);
Result->Data.setInt(!C.getLangOpts().Modules);
@@ -1167,11 +1323,13 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
SourceLocation AtLoc, IdentifierInfo *Id,
+ ObjCTypeParamList *typeParamList,
SourceLocation CLoc,
ObjCInterfaceDecl *PrevDecl,
bool IsInternal)
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc),
- redeclarable_base(C), TypeForDecl(nullptr), Data() {
+ redeclarable_base(C), TypeForDecl(nullptr), TypeParamList(nullptr),
+ Data() {
setPreviousDecl(PrevDecl);
// Copy the 'data' pointer over.
@@ -1179,6 +1337,8 @@ ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
Data = PrevDecl->Data;
setImplicit(IsInternal);
+
+ setTypeParamList(typeParamList);
}
void ObjCInterfaceDecl::LoadExternalDefinition() const {
@@ -1492,6 +1652,11 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
}
}
+QualType ObjCIvarDecl::getUsageType(QualType objectType) const {
+ return getType().substObjCMemberType(objectType, getDeclContext(),
+ ObjCSubstitutionContext::Property);
+}
+
//===----------------------------------------------------------------------===//
// ObjCAtDefsFieldDecl
//===----------------------------------------------------------------------===//
@@ -1648,17 +1813,34 @@ ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
void ObjCCategoryDecl::anchor() { }
+ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
+ SourceLocation ClassNameLoc,
+ SourceLocation CategoryNameLoc,
+ IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
+ ObjCTypeParamList *typeParamList,
+ SourceLocation IvarLBraceLoc,
+ SourceLocation IvarRBraceLoc)
+ : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
+ ClassInterface(IDecl), TypeParamList(nullptr),
+ NextClassCategory(nullptr), CategoryNameLoc(CategoryNameLoc),
+ IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc)
+{
+ setTypeParamList(typeParamList);
+}
+
ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id,
ObjCInterfaceDecl *IDecl,
+ ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc,
SourceLocation IvarRBraceLoc) {
ObjCCategoryDecl *CatDecl =
new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id,
- IDecl, IvarLBraceLoc, IvarRBraceLoc);
+ IDecl, typeParamList, IvarLBraceLoc,
+ IvarRBraceLoc);
if (IDecl) {
// Link this category into its class's category list.
CatDecl->NextClassCategory = IDecl->getCategoryListRaw();
@@ -1676,7 +1858,7 @@ ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(),
SourceLocation(), SourceLocation(),
- nullptr, nullptr);
+ nullptr, nullptr, nullptr);
}
ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
@@ -1688,6 +1870,15 @@ void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
getASTContext().setObjCImplementation(this, ImplD);
}
+void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) {
+ TypeParamList = TPL;
+ if (!TPL)
+ return;
+ // Set the declaration context of each of the type parameters.
+ for (auto typeParam : *TypeParamList)
+ typeParam->setDeclContext(this);
+}
+
//===----------------------------------------------------------------------===//
// ObjCCategoryImplDecl
@@ -1876,6 +2067,11 @@ ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
QualType(), nullptr, None);
}
+QualType ObjCPropertyDecl::getUsageType(QualType objectType) const {
+ return DeclType.substObjCMemberType(objectType, getDeclContext(),
+ ObjCSubstitutionContext::Property);
+}
+
//===----------------------------------------------------------------------===//
// ObjCPropertyImplDecl
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index d33093b8b5e1..3202d8c75436 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -44,6 +44,8 @@ namespace {
void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
QualType T);
+ void PrintObjCTypeParams(ObjCTypeParamList *Params);
+
public:
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0, bool PrintInstantiation = false)
@@ -962,6 +964,38 @@ void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
Out << ')';
}
+void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) {
+ Out << "<";
+ unsigned First = true;
+ for (auto *Param : *Params) {
+ if (First) {
+ First = false;
+ } else {
+ Out << ", ";
+ }
+
+ switch (Param->getVariance()) {
+ case ObjCTypeParamVariance::Invariant:
+ break;
+
+ case ObjCTypeParamVariance::Covariant:
+ Out << "__covariant ";
+ break;
+
+ case ObjCTypeParamVariance::Contravariant:
+ Out << "__contravariant ";
+ break;
+ }
+
+ Out << Param->getDeclName().getAsString();
+
+ if (Param->hasExplicitBound()) {
+ Out << " : " << Param->getUnderlyingType().getAsString(Policy);
+ }
+ }
+ Out << ">";
+}
+
void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isInstanceMethod())
Out << "- ";
@@ -1037,14 +1071,24 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (!OID->isThisDeclarationADefinition()) {
- Out << "@class " << I << ";";
+ Out << "@class " << I;
+
+ if (auto TypeParams = OID->getTypeParamListAsWritten()) {
+ PrintObjCTypeParams(TypeParams);
+ }
+
+ Out << ";";
return;
}
bool eolnOut = false;
+ Out << "@interface " << I;
+
+ if (auto TypeParams = OID->getTypeParamListAsWritten()) {
+ PrintObjCTypeParams(TypeParams);
+ }
+
if (SID)
- Out << "@interface " << I << " : " << *SID;
- else
- Out << "@interface " << I;
+ Out << " : " << OID->getSuperClass()->getName();
// Protocols?
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
@@ -1107,7 +1151,11 @@ void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
}
void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
- Out << "@interface " << *PID->getClassInterface() << '(' << *PID << ")\n";
+ Out << "@interface " << *PID->getClassInterface();
+ if (auto TypeParams = PID->getTypeParamList()) {
+ PrintObjCTypeParams(TypeParams);
+ }
+ Out << "(" << *PID << ")\n";
if (PID->ivar_size() > 0) {
Out << "{\n";
Indentation += Policy.Indentation;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 87f9ffba78e3..2e066b2c42c6 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -3748,6 +3748,16 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
return nullptr;
}
+QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const {
+ if (isClassReceiver())
+ return ctx.getObjCInterfaceType(getClassReceiver());
+
+ if (isSuperReceiver())
+ return getSuperReceiverType();
+
+ return getBase()->getType();
+}
+
StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
switch (getBridgeKind()) {
case OBC_Bridge:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 0134c090d67e..dac803e5d2ff 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -2379,6 +2379,10 @@ void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
}
void CXXNameMangler::mangleType(const ObjCObjectType *T) {
+ // Treat __kindof as a vendor extended type qualifier.
+ if (T->isKindOfType())
+ Out << "U8__kindof";
+
if (!T->qual_empty()) {
// Mangle protocol qualifiers.
SmallString<64> QualStr;
@@ -2391,7 +2395,16 @@ void CXXNameMangler::mangleType(const ObjCObjectType *T) {
QualOS.flush();
Out << 'U' << QualStr.size() << QualStr;
}
+
mangleType(T->getBaseType());
+
+ if (T->isSpecialized()) {
+ // Mangle type arguments as I <type>+ E
+ Out << 'I';
+ for (auto typeArg : T->getTypeArgs())
+ mangleType(typeArg);
+ Out << 'E';
+ }
}
void CXXNameMangler::mangleType(const BlockPointerType *T) {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 541bd1ebdf88..cee5fee83913 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -466,18 +466,976 @@ const RecordType *Type::getAsUnionType() const {
return nullptr;
}
+bool Type::isObjCIdOrObjectKindOfType(const ASTContext &ctx,
+ const ObjCObjectType *&bound) const {
+ bound = nullptr;
+
+ const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>();
+ if (!OPT)
+ return false;
+
+ // Easy case: id.
+ if (OPT->isObjCIdType())
+ return true;
+
+ // If it's not a __kindof type, reject it now.
+ if (!OPT->isKindOfType())
+ return false;
+
+ // If it's Class or qualified Class, it's not an object type.
+ if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
+ return false;
+
+ // Figure out the type bound for the __kindof type.
+ bound = OPT->getObjectType()->stripObjCKindOfTypeAndQuals(ctx)
+ ->getAs<ObjCObjectType>();
+ return true;
+}
+
+bool Type::isObjCClassOrClassKindOfType() const {
+ const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>();
+ if (!OPT)
+ return false;
+
+ // Easy case: Class.
+ if (OPT->isObjCClassType())
+ return true;
+
+ // If it's not a __kindof type, reject it now.
+ if (!OPT->isKindOfType())
+ return false;
+
+ // If it's Class or qualified Class, it's a class __kindof type.
+ return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType();
+}
+
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
- ObjCProtocolDecl * const *Protocols,
- unsigned NumProtocols)
- : Type(ObjCObject, Canonical, false, false, false, false),
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf)
+ : Type(ObjCObject, Canonical, Base->isDependentType(),
+ Base->isInstantiationDependentType(),
+ Base->isVariablyModifiedType(),
+ Base->containsUnexpandedParameterPack()),
BaseType(Base)
{
- ObjCObjectTypeBits.NumProtocols = NumProtocols;
- assert(getNumProtocols() == NumProtocols &&
+ ObjCObjectTypeBits.IsKindOf = isKindOf;
+
+ ObjCObjectTypeBits.NumTypeArgs = typeArgs.size();
+ assert(getTypeArgsAsWritten().size() == typeArgs.size() &&
+ "bitfield overflow in type argument count");
+ ObjCObjectTypeBits.NumProtocols = protocols.size();
+ assert(getNumProtocols() == protocols.size() &&
"bitfield overflow in protocol count");
- if (NumProtocols)
- memcpy(getProtocolStorage(), Protocols,
- NumProtocols * sizeof(ObjCProtocolDecl*));
+ if (!typeArgs.empty())
+ memcpy(getTypeArgStorage(), typeArgs.data(),
+ typeArgs.size() * sizeof(QualType));
+ if (!protocols.empty())
+ memcpy(getProtocolStorage(), protocols.data(),
+ protocols.size() * sizeof(ObjCProtocolDecl*));
+
+ for (auto typeArg : typeArgs) {
+ if (typeArg->isDependentType())
+ setDependent();
+ else if (typeArg->isInstantiationDependentType())
+ setInstantiationDependent();
+
+ if (typeArg->containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
+ }
+}
+
+bool ObjCObjectType::isSpecialized() const {
+ // If we have type arguments written here, the type is specialized.
+ if (ObjCObjectTypeBits.NumTypeArgs > 0)
+ return true;
+
+ // Otherwise, check whether the base type is specialized.
+ if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
+ // Terminate when we reach an interface type.
+ if (isa<ObjCInterfaceType>(objcObject))
+ return false;
+
+ return objcObject->isSpecialized();
+ }
+
+ // Not specialized.
+ return false;
+}
+
+ArrayRef<QualType> ObjCObjectType::getTypeArgs() const {
+ // We have type arguments written on this type.
+ if (isSpecializedAsWritten())
+ return getTypeArgsAsWritten();
+
+ // Look at the base type, which might have type arguments.
+ if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
+ // Terminate when we reach an interface type.
+ if (isa<ObjCInterfaceType>(objcObject))
+ return { };
+
+ return objcObject->getTypeArgs();
+ }
+
+ // No type arguments.
+ return { };
+}
+
+bool ObjCObjectType::isKindOfType() const {
+ if (isKindOfTypeAsWritten())
+ return true;
+
+ // Look at the base type, which might have type arguments.
+ if (auto objcObject = getBaseType()->getAs<ObjCObjectType>()) {
+ // Terminate when we reach an interface type.
+ if (isa<ObjCInterfaceType>(objcObject))
+ return false;
+
+ return objcObject->isKindOfType();
+ }
+
+ // Not a "__kindof" type.
+ return false;
+}
+
+QualType ObjCObjectType::stripObjCKindOfTypeAndQuals(
+ const ASTContext &ctx) const {
+ if (!isKindOfType() && qual_empty())
+ return QualType(this, 0);
+
+ // Recursively strip __kindof.
+ SplitQualType splitBaseType = getBaseType().split();
+ QualType baseType(splitBaseType.Ty, 0);
+ if (const ObjCObjectType *baseObj
+ = splitBaseType.Ty->getAs<ObjCObjectType>()) {
+ baseType = baseObj->stripObjCKindOfTypeAndQuals(ctx);
+ }
+
+ return ctx.getObjCObjectType(ctx.getQualifiedType(baseType,
+ splitBaseType.Quals),
+ getTypeArgsAsWritten(),
+ /*protocols=*/{ },
+ /*isKindOf=*/false);
+}
+
+const ObjCObjectPointerType *ObjCObjectPointerType::stripObjCKindOfTypeAndQuals(
+ const ASTContext &ctx) const {
+ if (!isKindOfType() && qual_empty())
+ return this;
+
+ QualType obj = getObjectType()->stripObjCKindOfTypeAndQuals(ctx);
+ return ctx.getObjCObjectPointerType(obj)->castAs<ObjCObjectPointerType>();
+}
+
+namespace {
+
+template<typename F>
+QualType simpleTransform(ASTContext &ctx, QualType type, F &&f);
+
+/// Visitor used by simpleTransform() to perform the transformation.
+template<typename F>
+struct SimpleTransformVisitor
+ : public TypeVisitor<SimpleTransformVisitor<F>, QualType> {
+ ASTContext &Ctx;
+ F &&TheFunc;
+
+ QualType recurse(QualType type) {
+ return simpleTransform(Ctx, type, std::move(TheFunc));
+ }
+
+public:
+ SimpleTransformVisitor(ASTContext &ctx, F &&f) : Ctx(ctx), TheFunc(std::move(f)) { }
+
+ // None of the clients of this transformation can occur where
+ // there are dependent types, so skip dependent types.
+#define TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) \
+ QualType Visit##Class##Type(const Class##Type *T) { return QualType(T, 0); }
+#include "clang/AST/TypeNodes.def"
+
+#define TRIVIAL_TYPE_CLASS(Class) \
+ QualType Visit##Class##Type(const Class##Type *T) { return QualType(T, 0); }
+
+ TRIVIAL_TYPE_CLASS(Builtin)
+
+ QualType VisitComplexType(const ComplexType *T) {
+ QualType elementType = recurse(T->getElementType());
+ if (elementType.isNull())
+ return QualType();
+
+ if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getComplexType(elementType);
+ }
+
+ QualType VisitPointerType(const PointerType *T) {
+ QualType pointeeType = recurse(T->getPointeeType());
+ if (pointeeType.isNull())
+ return QualType();
+
+ if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getPointerType(pointeeType);
+ }
+
+ QualType VisitBlockPointerType(const BlockPointerType *T) {
+ QualType pointeeType = recurse(T->getPointeeType());
+ if (pointeeType.isNull())
+ return QualType();
+
+ if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getBlockPointerType(pointeeType);
+ }
+
+ QualType VisitLValueReferenceType(const LValueReferenceType *T) {
+ QualType pointeeType = recurse(T->getPointeeTypeAsWritten());
+ if (pointeeType.isNull())
+ return QualType();
+
+ if (pointeeType.getAsOpaquePtr()
+ == T->getPointeeTypeAsWritten().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getLValueReferenceType(pointeeType, T->isSpelledAsLValue());
+ }
+
+ QualType VisitRValueReferenceType(const RValueReferenceType *T) {
+ QualType pointeeType = recurse(T->getPointeeTypeAsWritten());
+ if (pointeeType.isNull())
+ return QualType();
+
+ if (pointeeType.getAsOpaquePtr()
+ == T->getPointeeTypeAsWritten().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getRValueReferenceType(pointeeType);
+ }
+
+ QualType VisitMemberPointerType(const MemberPointerType *T) {
+ QualType pointeeType = recurse(T->getPointeeType());
+ if (pointeeType.isNull())
+ return QualType();
+
+ if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getMemberPointerType(pointeeType, T->getClass());
+ }
+
+ QualType VisitConstantArrayType(const ConstantArrayType *T) {
+ QualType elementType = recurse(T->getElementType());
+ if (elementType.isNull())
+ return QualType();
+
+ if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getConstantArrayType(elementType, T->getSize(),
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers());
+ }
+
+ QualType VisitVariableArrayType(const VariableArrayType *T) {
+ QualType elementType = recurse(T->getElementType());
+ if (elementType.isNull())
+ return QualType();
+
+ if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getVariableArrayType(elementType, T->getSizeExpr(),
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers(),
+ T->getBracketsRange());
+ }
+
+ QualType VisitIncompleteArrayType(const IncompleteArrayType *T) {
+ QualType elementType = recurse(T->getElementType());
+ if (elementType.isNull())
+ return QualType();
+
+ if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getIncompleteArrayType(elementType, T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers());
+ }
+
+ QualType VisitVectorType(const VectorType *T) {
+ QualType elementType = recurse(T->getElementType());
+ if (elementType.isNull())
+ return QualType();
+
+ if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getVectorType(elementType, T->getNumElements(),
+ T->getVectorKind());
+ }
+
+ QualType VisitExtVectorType(const ExtVectorType *T) {
+ QualType elementType = recurse(T->getElementType());
+ if (elementType.isNull())
+ return QualType();
+
+ if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getExtVectorType(elementType, T->getNumElements());
+ }
+
+ QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
+ QualType returnType = recurse(T->getReturnType());
+ if (returnType.isNull())
+ return QualType();
+
+ if (returnType.getAsOpaquePtr() == T->getReturnType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getFunctionNoProtoType(returnType, T->getExtInfo());
+ }
+
+ QualType VisitFunctionProtoType(const FunctionProtoType *T) {
+ QualType returnType = recurse(T->getReturnType());
+ if (returnType.isNull())
+ return QualType();
+
+ // Transform parameter types.
+ SmallVector<QualType, 4> paramTypes;
+ bool paramChanged = false;
+ for (auto paramType : T->getParamTypes()) {
+ QualType newParamType = recurse(paramType);
+ if (newParamType.isNull())
+ return QualType();
+
+ if (newParamType.getAsOpaquePtr() != paramType.getAsOpaquePtr())
+ paramChanged = true;
+
+ paramTypes.push_back(newParamType);
+ }
+
+ // Transform extended info.
+ FunctionProtoType::ExtProtoInfo info = T->getExtProtoInfo();
+ bool exceptionChanged = false;
+ if (info.ExceptionSpec.Type == EST_Dynamic) {
+ SmallVector<QualType, 4> exceptionTypes;
+ for (auto exceptionType : info.ExceptionSpec.Exceptions) {
+ QualType newExceptionType = recurse(exceptionType);
+ if (newExceptionType.isNull())
+ return QualType();
+
+ if (newExceptionType.getAsOpaquePtr()
+ != exceptionType.getAsOpaquePtr())
+ exceptionChanged = true;
+
+ exceptionTypes.push_back(newExceptionType);
+ }
+
+ if (exceptionChanged) {
+ unsigned size = sizeof(QualType) * exceptionTypes.size();
+ void *mem = Ctx.Allocate(size, llvm::alignOf<QualType>());
+ memcpy(mem, exceptionTypes.data(), size);
+ info.ExceptionSpec.Exceptions
+ = llvm::makeArrayRef((QualType *)mem, exceptionTypes.size());
+ }
+ }
+
+ if (returnType.getAsOpaquePtr() == T->getReturnType().getAsOpaquePtr() &&
+ !paramChanged && !exceptionChanged)
+ return QualType(T, 0);
+
+ return Ctx.getFunctionType(returnType, paramTypes, info);
+ }
+
+ QualType VisitParenType(const ParenType *T) {
+ QualType innerType = recurse(T->getInnerType());
+ if (innerType.isNull())
+ return QualType();
+
+ if (innerType.getAsOpaquePtr() == T->getInnerType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getParenType(innerType);
+ }
+
+ TRIVIAL_TYPE_CLASS(Typedef)
+
+ QualType VisitAdjustedType(const AdjustedType *T) {
+ QualType originalType = recurse(T->getOriginalType());
+ if (originalType.isNull())
+ return QualType();
+
+ QualType adjustedType = recurse(T->getAdjustedType());
+ if (adjustedType.isNull())
+ return QualType();
+
+ if (originalType.getAsOpaquePtr()
+ == T->getOriginalType().getAsOpaquePtr() &&
+ adjustedType.getAsOpaquePtr() == T->getAdjustedType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getAdjustedType(originalType, adjustedType);
+ }
+
+ QualType VisitDecayedType(const DecayedType *T) {
+ QualType originalType = recurse(T->getOriginalType());
+ if (originalType.isNull())
+ return QualType();
+
+ if (originalType.getAsOpaquePtr()
+ == T->getOriginalType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getDecayedType(originalType);
+ }
+
+ TRIVIAL_TYPE_CLASS(TypeOfExpr)
+ TRIVIAL_TYPE_CLASS(TypeOf)
+ TRIVIAL_TYPE_CLASS(Decltype)
+ TRIVIAL_TYPE_CLASS(UnaryTransform)
+ TRIVIAL_TYPE_CLASS(Record)
+ TRIVIAL_TYPE_CLASS(Enum)
+
+ // FIXME: Non-trivial to implement, but important for C++
+ TRIVIAL_TYPE_CLASS(Elaborated)
+
+ QualType VisitAttributedType(const AttributedType *T) {
+ QualType modifiedType = recurse(T->getModifiedType());
+ if (modifiedType.isNull())
+ return QualType();
+
+ QualType equivalentType = recurse(T->getEquivalentType());
+ if (equivalentType.isNull())
+ return QualType();
+
+ if (modifiedType.getAsOpaquePtr()
+ == T->getModifiedType().getAsOpaquePtr() &&
+ equivalentType.getAsOpaquePtr()
+ == T->getEquivalentType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getAttributedType(T->getAttrKind(), modifiedType,
+ equivalentType);
+ }
+
+ QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
+ QualType replacementType = recurse(T->getReplacementType());
+ if (replacementType.isNull())
+ return QualType();
+
+ if (replacementType.getAsOpaquePtr()
+ == T->getReplacementType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getSubstTemplateTypeParmType(T->getReplacedParameter(),
+ replacementType);
+ }
+
+ // FIXME: Non-trivial to implement, but important for C++
+ TRIVIAL_TYPE_CLASS(TemplateSpecialization)
+
+ QualType VisitAutoType(const AutoType *T) {
+ if (!T->isDeduced())
+ return QualType(T, 0);
+
+ QualType deducedType = recurse(T->getDeducedType());
+ if (deducedType.isNull())
+ return QualType();
+
+ if (deducedType.getAsOpaquePtr()
+ == T->getDeducedType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getAutoType(deducedType, T->isDecltypeAuto(),
+ T->isDependentType());
+ }
+
+ // FIXME: Non-trivial to implement, but important for C++
+ TRIVIAL_TYPE_CLASS(PackExpansion)
+
+ QualType VisitObjCObjectType(const ObjCObjectType *T) {
+ QualType baseType = recurse(T->getBaseType());
+ if (baseType.isNull())
+ return QualType();
+
+ // Transform type arguments.
+ bool typeArgChanged = false;
+ SmallVector<QualType, 4> typeArgs;
+ for (auto typeArg : T->getTypeArgsAsWritten()) {
+ QualType newTypeArg = recurse(typeArg);
+ if (newTypeArg.isNull())
+ return QualType();
+
+ if (newTypeArg.getAsOpaquePtr() != typeArg.getAsOpaquePtr())
+ typeArgChanged = true;
+
+ typeArgs.push_back(newTypeArg);
+ }
+
+ if (baseType.getAsOpaquePtr() == T->getBaseType().getAsOpaquePtr() &&
+ !typeArgChanged)
+ return QualType(T, 0);
+
+ return Ctx.getObjCObjectType(baseType, typeArgs,
+ llvm::makeArrayRef(T->qual_begin(),
+ T->getNumProtocols()),
+ T->isKindOfTypeAsWritten());
+ }
+
+ TRIVIAL_TYPE_CLASS(ObjCInterface)
+
+ QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+ QualType pointeeType = recurse(T->getPointeeType());
+ if (pointeeType.isNull())
+ return QualType();
+
+ if (pointeeType.getAsOpaquePtr()
+ == T->getPointeeType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getObjCObjectPointerType(pointeeType);
+ }
+
+ QualType VisitAtomicType(const AtomicType *T) {
+ QualType valueType = recurse(T->getValueType());
+ if (valueType.isNull())
+ return QualType();
+
+ if (valueType.getAsOpaquePtr()
+ == T->getValueType().getAsOpaquePtr())
+ return QualType(T, 0);
+
+ return Ctx.getAtomicType(valueType);
+ }
+
+#undef TRIVIAL_TYPE_CLASS
+};
+
+/// Perform a simple type transformation that does not change the
+/// semantics of the type.
+template<typename F>
+QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) {
+ // Transform the type. If it changed, return the transformed result.
+ QualType transformed = f(type);
+ if (transformed.getAsOpaquePtr() != type.getAsOpaquePtr())
+ return transformed;
+
+ // Split out the qualifiers from the type.
+ SplitQualType splitType = type.split();
+
+ // Visit the type itself.
+ SimpleTransformVisitor<F> visitor(ctx, std::move(f));
+ QualType result = visitor.Visit(splitType.Ty);
+ if (result.isNull())
+ return result;
+
+ // Reconstruct the transformed type by applying the local qualifiers
+ // from the split type.
+ return ctx.getQualifiedType(result, splitType.Quals);
+}
+
+} // end anonymous namespace
+
+/// Substitute the given type arguments for Objective-C type
+/// parameters within the given type, recursively.
+QualType QualType::substObjCTypeArgs(
+ ASTContext &ctx,
+ ArrayRef<QualType> typeArgs,
+ ObjCSubstitutionContext context) const {
+ return simpleTransform(ctx, *this,
+ [&](QualType type) -> QualType {
+ SplitQualType splitType = type.split();
+
+ // Replace an Objective-C type parameter reference with the corresponding
+ // type argument.
+ if (const auto *typedefTy = dyn_cast<TypedefType>(splitType.Ty)) {
+ if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(typedefTy->getDecl())) {
+ // If we have type arguments, use them.
+ if (!typeArgs.empty()) {
+ // FIXME: Introduce SubstObjCTypeParamType ?
+ QualType argType = typeArgs[typeParam->getIndex()];
+ return ctx.getQualifiedType(argType, splitType.Quals);
+ }
+
+ switch (context) {
+ case ObjCSubstitutionContext::Ordinary:
+ case ObjCSubstitutionContext::Parameter:
+ case ObjCSubstitutionContext::Superclass:
+ // Substitute the bound.
+ return ctx.getQualifiedType(typeParam->getUnderlyingType(),
+ splitType.Quals);
+
+ case ObjCSubstitutionContext::Result:
+ case ObjCSubstitutionContext::Property: {
+ // Substitute the __kindof form of the underlying type.
+ const auto *objPtr = typeParam->getUnderlyingType()
+ ->castAs<ObjCObjectPointerType>();
+
+ // __kindof types, id, and Class don't need an additional
+ // __kindof.
+ if (objPtr->isKindOfType() || objPtr->isObjCIdOrClassType())
+ return ctx.getQualifiedType(typeParam->getUnderlyingType(),
+ splitType.Quals);
+
+ // Add __kindof.
+ const auto *obj = objPtr->getObjectType();
+ QualType resultTy = ctx.getObjCObjectType(obj->getBaseType(),
+ obj->getTypeArgsAsWritten(),
+ obj->getProtocols(),
+ /*isKindOf=*/true);
+
+ // Rebuild object pointer type.
+ resultTy = ctx.getObjCObjectPointerType(resultTy);
+ return ctx.getQualifiedType(resultTy, splitType.Quals);
+ }
+ }
+ }
+ }
+
+ // If we have a function type, update the context appropriately.
+ if (const auto *funcType = dyn_cast<FunctionType>(splitType.Ty)) {
+ // Substitute result type.
+ QualType returnType = funcType->getReturnType().substObjCTypeArgs(
+ ctx,
+ typeArgs,
+ ObjCSubstitutionContext::Result);
+ if (returnType.isNull())
+ return QualType();
+
+ // Handle non-prototyped functions, which only substitute into the result
+ // type.
+ if (isa<FunctionNoProtoType>(funcType)) {
+ // If the return type was unchanged, do nothing.
+ if (returnType.getAsOpaquePtr()
+ == funcType->getReturnType().getAsOpaquePtr())
+ return type;
+
+ // Otherwise, build a new type.
+ return ctx.getFunctionNoProtoType(returnType, funcType->getExtInfo());
+ }
+
+ const auto *funcProtoType = cast<FunctionProtoType>(funcType);
+
+ // Transform parameter types.
+ SmallVector<QualType, 4> paramTypes;
+ bool paramChanged = false;
+ for (auto paramType : funcProtoType->getParamTypes()) {
+ QualType newParamType = paramType.substObjCTypeArgs(
+ ctx,
+ typeArgs,
+ ObjCSubstitutionContext::Parameter);
+ if (newParamType.isNull())
+ return QualType();
+
+ if (newParamType.getAsOpaquePtr() != paramType.getAsOpaquePtr())
+ paramChanged = true;
+
+ paramTypes.push_back(newParamType);
+ }
+
+ // Transform extended info.
+ FunctionProtoType::ExtProtoInfo info = funcProtoType->getExtProtoInfo();
+ bool exceptionChanged = false;
+ if (info.ExceptionSpec.Type == EST_Dynamic) {
+ SmallVector<QualType, 4> exceptionTypes;
+ for (auto exceptionType : info.ExceptionSpec.Exceptions) {
+ QualType newExceptionType = exceptionType.substObjCTypeArgs(
+ ctx,
+ typeArgs,
+ ObjCSubstitutionContext::Ordinary);
+ if (newExceptionType.isNull())
+ return QualType();
+
+ if (newExceptionType.getAsOpaquePtr()
+ != exceptionType.getAsOpaquePtr())
+ exceptionChanged = true;
+
+ exceptionTypes.push_back(newExceptionType);
+ }
+
+ if (exceptionChanged) {
+ unsigned size = sizeof(QualType) * exceptionTypes.size();
+ void *mem = ctx.Allocate(size, llvm::alignOf<QualType>());
+ memcpy(mem, exceptionTypes.data(), size);
+ info.ExceptionSpec.Exceptions
+ = llvm::makeArrayRef((QualType *)mem, exceptionTypes.size());
+ }
+ }
+
+ if (returnType.getAsOpaquePtr()
+ == funcProtoType->getReturnType().getAsOpaquePtr() &&
+ !paramChanged && !exceptionChanged)
+ return type;
+
+ return ctx.getFunctionType(returnType, paramTypes, info);
+ }
+
+ // Substitute into the type arguments of a specialized Objective-C object
+ // type.
+ if (const auto *objcObjectType = dyn_cast<ObjCObjectType>(splitType.Ty)) {
+ if (objcObjectType->isSpecializedAsWritten()) {
+ SmallVector<QualType, 4> newTypeArgs;
+ bool anyChanged = false;
+ for (auto typeArg : objcObjectType->getTypeArgsAsWritten()) {
+ QualType newTypeArg = typeArg.substObjCTypeArgs(
+ ctx, typeArgs,
+ ObjCSubstitutionContext::Ordinary);
+ if (newTypeArg.isNull())
+ return QualType();
+
+ if (newTypeArg.getAsOpaquePtr() != typeArg.getAsOpaquePtr()) {
+ // If we're substituting based on an unspecialized context type,
+ // produce an unspecialized type.
+ ArrayRef<ObjCProtocolDecl *> protocols(
+ objcObjectType->qual_begin(),
+ objcObjectType->getNumProtocols());
+ if (typeArgs.empty() &&
+ context != ObjCSubstitutionContext::Superclass) {
+ return ctx.getObjCObjectType(
+ objcObjectType->getBaseType(), { },
+ protocols,
+ objcObjectType->isKindOfTypeAsWritten());
+ }
+
+ anyChanged = true;
+ }
+
+ newTypeArgs.push_back(newTypeArg);
+ }
+
+ if (anyChanged) {
+ ArrayRef<ObjCProtocolDecl *> protocols(
+ objcObjectType->qual_begin(),
+ objcObjectType->getNumProtocols());
+ return ctx.getObjCObjectType(objcObjectType->getBaseType(),
+ newTypeArgs, protocols,
+ objcObjectType->isKindOfTypeAsWritten());
+ }
+ }
+
+ return type;
+ }
+
+ return type;
+ });
+}
+
+QualType QualType::substObjCMemberType(QualType objectType,
+ const DeclContext *dc,
+ ObjCSubstitutionContext context) const {
+ if (auto subs = objectType->getObjCSubstitutions(dc))
+ return substObjCTypeArgs(dc->getParentASTContext(), *subs, context);
+
+ return *this;
+}
+
+QualType QualType::stripObjCKindOfType(const ASTContext &constCtx) const {
+ // FIXME: Because ASTContext::getAttributedType() is non-const.
+ auto &ctx = const_cast<ASTContext &>(constCtx);
+ return simpleTransform(ctx, *this,
+ [&](QualType type) -> QualType {
+ SplitQualType splitType = type.split();
+ if (auto *objType = splitType.Ty->getAs<ObjCObjectType>()) {
+ if (!objType->isKindOfType())
+ return type;
+
+ QualType baseType
+ = objType->getBaseType().stripObjCKindOfType(ctx);
+ return ctx.getQualifiedType(
+ ctx.getObjCObjectType(baseType,
+ objType->getTypeArgsAsWritten(),
+ objType->getProtocols(),
+ /*isKindOf=*/false),
+ splitType.Quals);
+ }
+
+ return type;
+ });
+}
+
+Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
+ const DeclContext *dc) const {
+ // Look through method scopes.
+ if (auto method = dyn_cast<ObjCMethodDecl>(dc))
+ dc = method->getDeclContext();
+
+ // Find the class or category in which the type we're substituting
+ // was declared.
+ const ObjCInterfaceDecl *dcClassDecl = dyn_cast<ObjCInterfaceDecl>(dc);
+ const ObjCCategoryDecl *dcCategoryDecl = nullptr;
+ ObjCTypeParamList *dcTypeParams = nullptr;
+ if (dcClassDecl) {
+ // If the class does not have any type parameters, there's no
+ // substitution to do.
+ dcTypeParams = dcClassDecl->getTypeParamList();
+ if (!dcTypeParams)
+ return None;
+ } else {
+ // If we are in neither a class mor a category, there's no
+ // substitution to perform.
+ dcCategoryDecl = dyn_cast<ObjCCategoryDecl>(dc);
+ if (!dcCategoryDecl)
+ return None;
+
+ // If the category does not have any type parameters, there's no
+ // substitution to do.
+ dcTypeParams = dcCategoryDecl->getTypeParamList();
+ if (!dcTypeParams)
+ return None;
+
+ dcClassDecl = dcCategoryDecl->getClassInterface();
+ if (!dcClassDecl)
+ return None;
+ }
+ assert(dcTypeParams && "No substitutions to perform");
+ assert(dcClassDecl && "No class context");
+
+ // Find the underlying object type.
+ const ObjCObjectType *objectType;
+ if (const auto *objectPointerType = getAs<ObjCObjectPointerType>()) {
+ objectType = objectPointerType->getObjectType();
+ } else if (getAs<BlockPointerType>()) {
+ ASTContext &ctx = dc->getParentASTContext();
+ objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, { })
+ ->castAs<ObjCObjectType>();;
+ } else {
+ objectType = getAs<ObjCObjectType>();
+ }
+
+ /// Extract the class from the receiver object type.
+ ObjCInterfaceDecl *curClassDecl = objectType ? objectType->getInterface()
+ : nullptr;
+ if (!curClassDecl) {
+ // If we don't have a context type (e.g., this is "id" or some
+ // variant thereof), substitute the bounds.
+ return llvm::ArrayRef<QualType>();
+ }
+
+ // Follow the superclass chain until we've mapped the receiver type
+ // to the same class as the context.
+ while (curClassDecl != dcClassDecl) {
+ // Map to the superclass type.
+ QualType superType = objectType->getSuperClassType();
+ if (superType.isNull()) {
+ objectType = nullptr;
+ break;
+ }
+
+ objectType = superType->castAs<ObjCObjectType>();
+ curClassDecl = objectType->getInterface();
+ }
+
+ // If we don't have a receiver type, or the receiver type does not
+ // have type arguments, substitute in the defaults.
+ if (!objectType || objectType->isUnspecialized()) {
+ return llvm::ArrayRef<QualType>();
+ }
+
+ // The receiver type has the type arguments we want.
+ return objectType->getTypeArgs();
+}
+
+bool Type::acceptsObjCTypeParams() const {
+ if (auto *IfaceT = getAsObjCInterfaceType()) {
+ if (auto *ID = IfaceT->getInterface()) {
+ if (ID->getTypeParamList())
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ObjCObjectType::computeSuperClassTypeSlow() const {
+ // Retrieve the class declaration for this type. If there isn't one
+ // (e.g., this is some variant of "id" or "Class"), then there is no
+ // superclass type.
+ ObjCInterfaceDecl *classDecl = getInterface();
+ if (!classDecl) {
+ CachedSuperClassType.setInt(true);
+ return;
+ }
+
+ // Extract the superclass type.
+ const ObjCObjectType *superClassObjTy = classDecl->getSuperClassType();
+ if (!superClassObjTy) {
+ CachedSuperClassType.setInt(true);
+ return;
+ }
+
+ ObjCInterfaceDecl *superClassDecl = superClassObjTy->getInterface();
+ if (!superClassDecl) {
+ CachedSuperClassType.setInt(true);
+ return;
+ }
+
+ // If the superclass doesn't have type parameters, then there is no
+ // substitution to perform.
+ QualType superClassType(superClassObjTy, 0);
+ ObjCTypeParamList *superClassTypeParams = superClassDecl->getTypeParamList();
+ if (!superClassTypeParams) {
+ CachedSuperClassType.setPointerAndInt(
+ superClassType->castAs<ObjCObjectType>(), true);
+ return;
+ }
+
+ // If the superclass reference is unspecialized, return it.
+ if (superClassObjTy->isUnspecialized()) {
+ CachedSuperClassType.setPointerAndInt(superClassObjTy, true);
+ return;
+ }
+
+ // If the subclass is not parameterized, there aren't any type
+ // parameters in the superclass reference to substitute.
+ ObjCTypeParamList *typeParams = classDecl->getTypeParamList();
+ if (!typeParams) {
+ CachedSuperClassType.setPointerAndInt(
+ superClassType->castAs<ObjCObjectType>(), true);
+ return;
+ }
+
+ // If the subclass type isn't specialized, return the unspecialized
+ // superclass.
+ if (isUnspecialized()) {
+ QualType unspecializedSuper
+ = classDecl->getASTContext().getObjCInterfaceType(
+ superClassObjTy->getInterface());
+ CachedSuperClassType.setPointerAndInt(
+ unspecializedSuper->castAs<ObjCObjectType>(),
+ true);
+ return;
+ }
+
+ // Substitute the provided type arguments into the superclass type.
+ ArrayRef<QualType> typeArgs = getTypeArgs();
+ assert(typeArgs.size() == typeParams->size());
+ CachedSuperClassType.setPointerAndInt(
+ superClassType.substObjCTypeArgs(classDecl->getASTContext(), typeArgs,
+ ObjCSubstitutionContext::Superclass)
+ ->castAs<ObjCObjectType>(),
+ true);
+}
+
+const ObjCInterfaceType *ObjCObjectPointerType::getInterfaceType() const {
+ if (auto interfaceDecl = getObjectType()->getInterface()) {
+ return interfaceDecl->getASTContext().getObjCInterfaceType(interfaceDecl)
+ ->castAs<ObjCInterfaceType>();
+ }
+
+ return nullptr;
+}
+
+QualType ObjCObjectPointerType::getSuperClassType() const {
+ QualType superObjectType = getObjectType()->getSuperClassType();
+ if (superObjectType.isNull())
+ return superObjectType;
+
+ ASTContext &ctx = getInterfaceDecl()->getASTContext();
+ return ctx.getObjCObjectPointerType(superObjectType);
}
const ObjCObjectType *Type::getAsObjCQualifiedInterfaceType() const {
@@ -514,6 +1472,13 @@ const ObjCObjectPointerType *Type::getAsObjCQualifiedClassType() const {
return nullptr;
}
+const ObjCObjectType *Type::getAsObjCInterfaceType() const {
+ if (const ObjCObjectType *OT = getAs<ObjCObjectType>()) {
+ if (OT->getInterface())
+ return OT;
+ }
+ return nullptr;
+}
const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
if (OPT->getInterfaceType())
@@ -1927,7 +2892,9 @@ bool AttributedType::isCallingConv() const {
case attr_nonnull:
case attr_nullable:
case attr_null_unspecified:
+ case attr_objc_kindof:
return false;
+
case attr_pcs:
case attr_pcs_vfp:
case attr_cdecl:
@@ -2076,15 +3043,23 @@ QualifierCollector::apply(const ASTContext &Context, const Type *T) const {
void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID,
QualType BaseType,
- ObjCProtocolDecl * const *Protocols,
- unsigned NumProtocols) {
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf) {
ID.AddPointer(BaseType.getAsOpaquePtr());
- for (unsigned i = 0; i != NumProtocols; i++)
- ID.AddPointer(Protocols[i]);
+ ID.AddInteger(typeArgs.size());
+ for (auto typeArg : typeArgs)
+ ID.AddPointer(typeArg.getAsOpaquePtr());
+ ID.AddInteger(protocols.size());
+ for (auto proto : protocols)
+ ID.AddPointer(proto);
+ ID.AddBoolean(isKindOf);
}
void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getBaseType(), qual_begin(), getNumProtocols());
+ Profile(ID, getBaseType(), getTypeArgsAsWritten(),
+ llvm::makeArrayRef(qual_begin(), getNumProtocols()),
+ isKindOfTypeAsWritten());
}
namespace {
@@ -2495,6 +3470,39 @@ Optional<NullabilityKind> AttributedType::stripOuterNullability(QualType &T) {
return None;
}
+bool Type::isBlockCompatibleObjCPointerType(ASTContext &ctx) const {
+ const ObjCObjectPointerType *objcPtr = getAs<ObjCObjectPointerType>();
+ if (!objcPtr)
+ return false;
+
+ if (objcPtr->isObjCIdType()) {
+ // id is always okay.
+ return true;
+ }
+
+ // Blocks are NSObjects.
+ if (ObjCInterfaceDecl *iface = objcPtr->getInterfaceDecl()) {
+ if (iface->getIdentifier() != ctx.getNSObjectName())
+ return false;
+
+ // Continue to check qualifiers, below.
+ } else if (objcPtr->isObjCQualifiedIdType()) {
+ // Continue to check qualifiers, below.
+ } else {
+ return false;
+ }
+
+ // Check protocol qualifiers.
+ for (ObjCProtocolDecl *proto : objcPtr->quals()) {
+ // Blocks conform to NSObject and NSCopying.
+ if (proto->getIdentifier() != ctx.getNSObjectName() &&
+ proto->getIdentifier() != ctx.getNSCopyingName())
+ return false;
+ }
+
+ return true;
+}
+
Qualifiers::ObjCLifetime Type::getObjCARCImplicitLifetime() const {
if (isObjCARCImplicitlyUnretainedType())
return Qualifiers::OCL_ExplicitNone;
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index c069eb061739..85bda6a06d97 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -19,6 +19,8 @@
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+static const unsigned TypeLocMaxDataAlign = llvm::alignOf<void *>();
+
//===----------------------------------------------------------------------===//
// TypeLoc Implementation
//===----------------------------------------------------------------------===//
@@ -125,6 +127,46 @@ void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
}
}
+namespace {
+ class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> {
+ TypeLoc Source;
+ public:
+ TypeLocCopier(TypeLoc source) : Source(source) { }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) { \
+ dest.copyLocal(Source.castAs<CLASS##TypeLoc>()); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+
+void TypeLoc::copy(TypeLoc other) {
+ assert(getFullDataSize() == other.getFullDataSize());
+
+ // If both data pointers are aligned to the maximum alignment, we
+ // can memcpy because getFullDataSize() accurately reflects the
+ // layout of the data.
+ if (reinterpret_cast<uintptr_t>(Data)
+ == llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(Data),
+ TypeLocMaxDataAlign) &&
+ reinterpret_cast<uintptr_t>(other.Data)
+ == llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(other.Data),
+ TypeLocMaxDataAlign)) {
+ memcpy(Data, other.Data, getFullDataSize());
+ return;
+ }
+
+ // Copy each of the pieces.
+ TypeLoc TL(getType(), Data);
+ do {
+ TypeLocCopier(other).Visit(TL);
+ other = other.getNextTypeLoc();
+ } while ((TL = TL.getNextTypeLoc()));
+}
+
SourceLocation TypeLoc::getBeginLoc() const {
TypeLoc Cur = *this;
TypeLoc LeftMost = Cur;
@@ -312,6 +354,33 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
return 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();
+ }
+
+ return SourceLocation();
+}
+
+void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setHasBaseTypeAsWritten(true);
+ setTypeArgsLAngleLoc(Loc);
+ setTypeArgsRAngleLoc(Loc);
+ for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) {
+ setTypeArgTInfo(i,
+ Context.getTrivialTypeSourceInfo(
+ getTypePtr()->getTypeArgsAsWritten()[i], Loc));
+ }
+ setProtocolLAngleLoc(Loc);
+ setProtocolRAngleLoc(Loc);
+ for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
+ setProtocolLoc(i, Loc);
+}
+
void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 9938170c321a..0bb50c6ba815 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -1129,6 +1129,9 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
T->getAttrKind() == AttributedType::attr_objc_ownership)
return printBefore(T->getEquivalentType(), OS);
+ if (T->getAttrKind() == AttributedType::attr_objc_kindof)
+ OS << "__kindof ";
+
printBefore(T->getModifiedType(), OS);
if (T->isMSTypeSpec()) {
@@ -1165,6 +1168,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
T->getAttrKind() == AttributedType::attr_objc_ownership)
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;
@@ -1310,59 +1316,61 @@ void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
raw_ostream &OS) {
- if (T->qual_empty())
+ if (T->qual_empty() && T->isUnspecializedAsWritten() &&
+ !T->isKindOfTypeAsWritten())
return printBefore(T->getBaseType(), OS);
+ if (T->isKindOfTypeAsWritten())
+ OS << "__kindof ";
+
print(T->getBaseType(), OS, StringRef());
- OS << '<';
- bool isFirst = true;
- for (const auto *I : T->quals()) {
- if (isFirst)
- isFirst = false;
- else
- OS << ',';
- OS << I->getName();
+
+ if (T->isSpecializedAsWritten()) {
+ bool isFirst = true;
+ OS << '<';
+ for (auto typeArg : T->getTypeArgsAsWritten()) {
+ if (isFirst)
+ isFirst = false;
+ else
+ OS << ",";
+
+ print(typeArg, OS, StringRef());
+ }
+ OS << '>';
}
- OS << '>';
+
+ if (!T->qual_empty()) {
+ bool isFirst = true;
+ OS << '<';
+ for (const auto *I : T->quals()) {
+ if (isFirst)
+ isFirst = false;
+ else
+ OS << ',';
+ OS << I->getName();
+ }
+ OS << '>';
+ }
+
spaceBeforePlaceHolder(OS);
}
void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
raw_ostream &OS) {
- if (T->qual_empty())
+ if (T->qual_empty() && T->isUnspecializedAsWritten() &&
+ !T->isKindOfTypeAsWritten())
return printAfter(T->getBaseType(), OS);
}
void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
raw_ostream &OS) {
- T->getPointeeType().getLocalQualifiers().print(OS, Policy,
- /*appendSpaceIfNonEmpty=*/true);
-
- assert(!T->isObjCSelType());
+ printBefore(T->getPointeeType(), OS);
- if (T->isObjCIdType() || T->isObjCQualifiedIdType())
- OS << "id";
- else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
- OS << "Class";
- else
- OS << T->getInterfaceDecl()->getName();
-
- if (!T->qual_empty()) {
- OS << '<';
- for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
- E = T->qual_end();
- I != E; ++I) {
- OS << (*I)->getName();
- if (I+1 != E)
- OS << ',';
- }
- OS << '>';
- }
-
+ // If we need to print the pointer, print it now.
if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&
!T->isObjCClassType() && !T->isObjCQualifiedClassType()) {
- OS << " *"; // Don't forget the implicit pointer.
- } else {
- spaceBeforePlaceHolder(OS);
+ if (HasEmptyPlaceHolder)
+ OS << ' ';
+ OS << '*';
}
}
void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp
index b6ef8226a9a9..069fcba474b2 100644
--- a/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -20,21 +20,21 @@ namespace clang {
namespace ast_matchers {
namespace internal {
-bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
+bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
-bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
-bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
-bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
@@ -51,7 +51,7 @@ void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
namespace {
typedef bool (*VariadicOperatorFunction)(
- const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
+ const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
template <VariadicOperatorFunction Func>
@@ -228,7 +228,7 @@ void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
}
-bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
+bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers) {
if (InnerMatchers.size() != 1)
@@ -248,7 +248,7 @@ bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
}
-bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers) {
@@ -262,7 +262,7 @@ bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
return true;
}
-bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers) {
@@ -279,7 +279,7 @@ bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
return Matched;
}
-bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers) {
diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
index 9930c530c081..96a78cd9f8fa 100644
--- a/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -216,7 +216,7 @@ private:
if (Code[Length] == Marker) {
Result->Kind = TokenInfo::TK_Literal;
Result->Text = Code.substr(0, Length + 1);
- Result->Value = Code.substr(1, Length - 1).str();
+ Result->Value = Code.substr(1, Length - 1);
Code = Code.drop_front(Length + 1);
return;
}
diff --git a/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp
index a88b70701234..9d8be4700581 100644
--- a/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -249,7 +249,7 @@ VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
setUnsigned(Unsigned);
}
-VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
+VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
setString(String);
}
@@ -319,7 +319,7 @@ const std::string &VariantValue::getString() const {
return *Value.String;
}
-void VariantValue::setString(const std::string &NewValue) {
+void VariantValue::setString(StringRef NewValue) {
reset();
Type = VT_String;
Value.String = new std::string(NewValue);
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index c46e2c7db380..1a636aefa639 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -19,6 +19,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Frontend/PCHContainerOperations.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
@@ -585,3 +586,5 @@ void FileManager::PrintStats() const {
//llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups;
}
+
+PCHContainerOperations::~PCHContainerOperations() {}
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 36fba994f1e7..dcb7603bf5ab 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -109,7 +109,8 @@ namespace {
WCHARSUPPORT = 0x04000,
HALFSUPPORT = 0x08000,
KEYCONCEPTS = 0x10000,
- KEYALL = (0x1ffff & ~KEYNOMS18 &
+ KEYOBJC2 = 0x20000,
+ KEYALL = (0x3ffff & ~KEYNOMS18 &
~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
};
@@ -144,6 +145,7 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
// in non-arc mode.
if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
+ if (LangOpts.ObjC2 && (Flags & KEYOBJC2)) return KS_Enabled;
if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future;
return KS_Disabled;
}
diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index 1a48a6c6a8d1..3846fecebf5d 100644
--- a/lib/Basic/Module.cpp
+++ b/lib/Basic/Module.cpp
@@ -82,10 +82,6 @@ bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
return true;
for (const Module *Current = this; Current; Current = Current->Parent) {
- if (!Current->MissingHeaders.empty()) {
- MissingHeader = Current->MissingHeaders.front();
- return false;
- }
for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
if (hasFeature(Current->Requirements[I].first, LangOpts, Target) !=
Current->Requirements[I].second) {
@@ -93,6 +89,10 @@ bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
return false;
}
}
+ if (!Current->MissingHeaders.empty()) {
+ MissingHeader = Current->MissingHeaders.front();
+ return false;
+ }
}
llvm_unreachable("could not find a reason why module is unavailable");
@@ -184,7 +184,11 @@ void Module::addRequirement(StringRef Feature, bool RequiredState,
}
void Module::markUnavailable(bool MissingRequirement) {
- if (!IsAvailable)
+ auto needUpdate = [MissingRequirement](Module *M) {
+ return M->IsAvailable || (!M->IsMissingRequirement && MissingRequirement);
+ };
+
+ if (!needUpdate(this))
return;
SmallVector<Module *, 2> Stack;
@@ -193,7 +197,7 @@ void Module::markUnavailable(bool MissingRequirement) {
Module *Current = Stack.back();
Stack.pop_back();
- if (!Current->IsAvailable)
+ if (!needUpdate(Current))
continue;
Current->IsAvailable = false;
@@ -201,7 +205,7 @@ void Module::markUnavailable(bool MissingRequirement) {
for (submodule_iterator Sub = Current->submodule_begin(),
SubEnd = Current->submodule_end();
Sub != SubEnd; ++Sub) {
- if ((*Sub)->IsAvailable)
+ if (needUpdate(*Sub))
Stack.push_back(*Sub);
}
}
diff --git a/lib/Basic/Sanitizers.cpp b/lib/Basic/Sanitizers.cpp
index d3676b6b465c..91b6b2dc74eb 100644
--- a/lib/Basic/Sanitizers.cpp
+++ b/lib/Basic/Sanitizers.cpp
@@ -14,34 +14,9 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/MathExtras.h"
using namespace clang;
-SanitizerSet::SanitizerSet() : Mask(0) {}
-
-bool SanitizerSet::has(SanitizerMask K) const {
- assert(llvm::countPopulation(K) == 1);
- return Mask & K;
-}
-
-bool SanitizerSet::hasOneOf(SanitizerMask K) const {
- return Mask & K;
-}
-
-void SanitizerSet::set(SanitizerMask K, bool Value) {
- assert(llvm::countPopulation(K) == 1);
- Mask = Value ? (Mask | K) : (Mask & ~K);
-}
-
-void SanitizerSet::clear() {
- Mask = 0;
-}
-
-bool SanitizerSet::empty() const {
- return Mask == 0;
-}
-
SanitizerMask clang::parseSanitizerValue(StringRef Value, bool AllowGroups) {
SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 856ad50d3782..dbd2f9ae9954 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -50,6 +50,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
LargeArrayAlign = 0;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
MaxVectorAlign = 0;
+ MaxTLSAlign = 0;
SimdDefaultAlign = 0;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 8f2bca051b67..3cf74bc84926 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -580,6 +580,8 @@ public:
PS4OSTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {
this->WCharType = this->UnsignedShort;
+ // On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits).
+ this->MaxTLSAlign = 256;
this->UserLabelPrefix = "";
switch (Triple.getArch()) {
@@ -863,6 +865,8 @@ public:
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;
bool hasFeature(StringRef Feature) const override;
+ void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
+ bool Enabled) const override;
void getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const override;
@@ -1036,7 +1040,6 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
if (Feature == "power8-vector") {
HasP8Vector = true;
- HasVSX = true;
continue;
}
@@ -1047,7 +1050,6 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
if (Feature == "direct-move") {
HasDirectMove = true;
- HasVSX = true;
continue;
}
@@ -1064,6 +1066,15 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
// TODO: Finish this list and add an assert that we've handled them
// all.
}
+ if (!HasVSX && (HasP8Vector || HasDirectMove)) {
+ if (HasP8Vector)
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector" <<
+ "-mno-vsx";
+ else if (HasDirectMove)
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move" <<
+ "-mno-vsx";
+ return false;
+ }
return true;
}
@@ -1285,6 +1296,11 @@ void PPCTargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
.Case("ppc64le", true)
.Case("pwr8", true)
.Default(false);
+ Features["vsx"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr8", true)
+ .Case("pwr7", true)
+ .Default(false);
}
bool PPCTargetInfo::hasFeature(StringRef Feature) const {
@@ -1301,6 +1317,39 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
.Default(false);
}
+/* There is no clear way for the target to know which of the features in the
+ final feature vector came from defaults and which are actually specified by
+ the user. To that end, we use the fact that this function is not called on
+ default features - only user specified ones. By the first time this
+ function is called, the default features are populated.
+ We then keep track of the features that the user specified so that we
+ can ensure we do not override a user's request (only defaults).
+ For example:
+ -mcpu=pwr8 -mno-vsx (should disable vsx and everything that depends on it)
+ -mcpu=pwr8 -mdirect-move -mno-vsx (should actually be diagnosed)
+
+NOTE: Do not call this from PPCTargetInfo::getDefaultFeatures
+*/
+void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
+ StringRef Name, bool Enabled) const {
+ static llvm::StringMap<bool> ExplicitFeatures;
+ ExplicitFeatures[Name] = Enabled;
+
+ // At this point, -mno-vsx turns off the dependent features but we respect
+ // the user's requests.
+ if (!Enabled && Name == "vsx") {
+ Features["direct-move"] = ExplicitFeatures["direct-move"];
+ Features["power8-vector"] = ExplicitFeatures["power8-vector"];
+ }
+ if ((Enabled && Name == "power8-vector") ||
+ (Enabled && Name == "direct-move")) {
+ if (ExplicitFeatures.find("vsx") == ExplicitFeatures.end()) {
+ Features["vsx"] = true;
+ }
+ }
+ Features[Name] = Enabled;
+}
+
const char * const PPCTargetInfo::GCCRegNames[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
@@ -1472,7 +1521,7 @@ public:
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::CharPtrBuiltinVaList;
}
- // PPC64 Linux-specifc ABI options.
+ // PPC64 Linux-specific ABI options.
bool setABI(const std::string &Name) override {
if (Name == "elfv1" || Name == "elfv1-qpx" || Name == "elfv2") {
ABI = Name;
@@ -3996,14 +4045,8 @@ class ARMTargetInfo : public TargetInfo {
FP_Neon
} FPMath;
- unsigned ArchISA;
- unsigned ArchKind;
- unsigned ArchProfile;
- unsigned ArchVersion;
-
unsigned FPU : 5;
- unsigned ShouldUseInlineAtomic : 1;
unsigned IsAAPCS : 1;
unsigned IsThumb : 1;
unsigned HWDiv : 2;
@@ -4025,6 +4068,37 @@ class ARMTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
+ static bool shouldUseInlineAtomic(const llvm::Triple &T) {
+ StringRef ArchName = T.getArchName();
+ if (T.getArch() == llvm::Triple::arm ||
+ T.getArch() == llvm::Triple::armeb) {
+ StringRef VersionStr;
+ if (ArchName.startswith("armv"))
+ VersionStr = ArchName.substr(4, 1);
+ else if (ArchName.startswith("armebv"))
+ VersionStr = ArchName.substr(6, 1);
+ else
+ return false;
+ unsigned Version;
+ if (VersionStr.getAsInteger(10, Version))
+ return false;
+ return Version >= 6;
+ }
+ assert(T.getArch() == llvm::Triple::thumb ||
+ T.getArch() == llvm::Triple::thumbeb);
+ StringRef VersionStr;
+ if (ArchName.startswith("thumbv"))
+ VersionStr = ArchName.substr(6, 1);
+ else if (ArchName.startswith("thumbebv"))
+ VersionStr = ArchName.substr(8, 1);
+ else
+ return false;
+ unsigned Version;
+ if (VersionStr.getAsInteger(10, Version))
+ return false;
+ return Version >= 7;
+ }
+
void setABIAAPCS() {
IsAAPCS = true;
@@ -4123,27 +4197,6 @@ class ARMTargetInfo : public TargetInfo {
// FIXME: Override "preferred align" for double and long long.
}
- void setArchInfo(StringRef ArchName) {
- ArchISA = llvm::ARMTargetParser::parseArchISA(ArchName);
- ArchKind = llvm::ARMTargetParser::parseArch(ArchName);
- ArchProfile = llvm::ARMTargetParser::parseArchProfile(ArchName);
- ArchVersion = llvm::ARMTargetParser::parseArchVersion(ArchName);
- }
-
- void setAtomic() {
- // Cortex M does not support 8 byte atomics, while general Thumb2 does.
- if (ArchProfile == llvm::ARM::PK_M) {
- MaxAtomicPromoteWidth = 32;
- if (ShouldUseInlineAtomic)
- MaxAtomicInlineWidth = 32;
- }
- else {
- MaxAtomicPromoteWidth = 64;
- if (ShouldUseInlineAtomic)
- MaxAtomicInlineWidth = 64;
- }
- }
-
public:
ARMTargetInfo(const llvm::Triple &Triple, bool IsBigEndian)
: TargetInfo(Triple), CPU("arm1136j-s"), FPMath(FP_Default),
@@ -4159,27 +4212,12 @@ public:
break;
}
- // if subArch is not specified Arc Info is based on the default CPU
- if (Triple.getSubArch() == llvm::Triple::SubArchType::NoSubArch) {
- unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU);
- setArchInfo(llvm::ARMTargetParser::getArchName(ArchKind));
- ShouldUseInlineAtomic = false;
- }
- else {
- setArchInfo(Triple.getArchName());
- // FIXME: Should't this be updated also when calling setCPU() ?
- // Doing so currently causes regressions
- ShouldUseInlineAtomic = (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) ||
- (ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7);
- }
-
// {} in inline assembly are neon specifiers, not assembly variant
// specifiers.
NoAsmVariants = true;
- // FIXME: Should't this be updated also when calling setCPU() ?
- // Doing so currently causes regressions
- IsThumb = (ArchISA == llvm::ARM::IK_THUMB);
+ // FIXME: Should we just treat this as a feature?
+ IsThumb = getTriple().getArchName().startswith("thumb");
// FIXME: This duplicates code from the driver that sets the -target-abi
// option - this code is used if -target-abi isn't passed and should
@@ -4224,7 +4262,10 @@ public:
// ARM targets default to using the ARM C++ ABI.
TheCXXABI.set(TargetCXXABI::GenericARM);
- setAtomic();
+ // ARM has atomics up to 8 bytes
+ MaxAtomicPromoteWidth = 64;
+ if (shouldUseInlineAtomic(getTriple()))
+ MaxAtomicInlineWidth = 64;
// Do force alignment of members that follow zero length bitfields. If
// the alignment of the zero-length bitfield is greater than the member
@@ -4255,6 +4296,11 @@ public:
// FIXME: This should be based on Arch attributes, not CPU names.
void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
+ StringRef ArchName = getTriple().getArchName();
+ unsigned ArchKind = llvm::ARMTargetParser::parseArch(ArchName);
+ bool IsV8 = (ArchKind == llvm::ARM::AK_ARMV8A ||
+ ArchKind == llvm::ARM::AK_ARMV8_1A);
+
if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore")
Features["vfp2"] = true;
else if (CPU == "cortex-a8" || CPU == "cortex-a9") {
@@ -4279,7 +4325,7 @@ public:
Features["hwdiv-arm"] = true;
Features["crc"] = true;
Features["crypto"] = true;
- } else if (CPU == "cortex-r5" || CPU == "cortex-r7" || ArchVersion == 8) {
+ } else if (CPU == "cortex-r5" || CPU == "cortex-r7" || IsV8) {
Features["hwdiv"] = true;
Features["hwdiv-arm"] = true;
} else if (CPU == "cortex-m3" || CPU == "cortex-m4" || CPU == "cortex-m7" ||
@@ -4362,14 +4408,26 @@ public:
.Case("hwdiv-arm", HWDiv & HWDivARM)
.Default(false);
}
- const char *getCPUAttr() const {
- const char *CPUAttr;
+ const char *getCPUDefineSuffix(StringRef Name) const {
+ if(Name == "generic") {
+ auto subarch = getTriple().getSubArch();
+ switch (subarch) {
+ case llvm::Triple::SubArchType::ARMSubArch_v8_1a:
+ return "8_1A";
+ default:
+ break;
+ }
+ }
+
+ unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(Name);
+ if (ArchKind == llvm::ARM::AK_INVALID)
+ return "";
+
// For most sub-arches, the build attribute CPU name is enough.
// For Cortex variants, it's slightly different.
switch(ArchKind) {
default:
- CPUAttr = llvm::ARMTargetParser::getCPUAttr(ArchKind);
- return CPUAttr ? CPUAttr : "" ;
+ return llvm::ARMTargetParser::getCPUAttr(ArchKind);
case llvm::ARM::AK_ARMV6M:
case llvm::ARM::AK_ARMV6SM:
return "6M";
@@ -4389,8 +4447,23 @@ public:
return "8_1A";
}
}
- const char *getCPUProfile() const {
- switch(ArchProfile) {
+ const char *getCPUProfile(StringRef Name) const {
+ if(Name == "generic") {
+ auto subarch = getTriple().getSubArch();
+ switch (subarch) {
+ case llvm::Triple::SubArchType::ARMSubArch_v8_1a:
+ return "A";
+ default:
+ break;
+ }
+ }
+
+ unsigned CPUArch = llvm::ARMTargetParser::parseCPUArch(Name);
+ if (CPUArch == llvm::ARM::AK_INVALID)
+ return "";
+
+ StringRef ArchName = llvm::ARMTargetParser::getArchName(CPUArch);
+ switch(llvm::ARMTargetParser::parseArchProfile(ArchName)) {
case llvm::ARM::PK_A:
return "A";
case llvm::ARM::PK_R:
@@ -4402,26 +4475,35 @@ public:
}
}
bool setCPU(const std::string &Name) override {
- unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(Name);
- if (ArchKind == llvm::ARM::AK_INVALID)
+ if (!getCPUDefineSuffix(Name))
return false;
- setArchInfo(llvm::ARMTargetParser::getArchName(ArchKind));
- setAtomic();
+
+ // Cortex M does not support 8 byte atomics, while general Thumb2 does.
+ StringRef Profile = getCPUProfile(Name);
+ if (Profile == "M" && MaxAtomicInlineWidth) {
+ MaxAtomicPromoteWidth = 32;
+ MaxAtomicInlineWidth = 32;
+ }
+
CPU = Name;
return true;
}
bool setFPMath(StringRef Name) override;
- bool supportsThumb(StringRef CPUAttr) const {
- return CPUAttr.count('T') || ArchVersion >= 6;
- }
- bool supportsThumb2(StringRef CPUAttr) const {
- return CPUAttr.equals("6T2") || ArchVersion >= 7;
+ bool supportsThumb(StringRef ArchName, StringRef CPUArch,
+ unsigned CPUArchVer) const {
+ return CPUArchVer >= 7 || (CPUArch.find('T') != StringRef::npos) ||
+ (CPUArch.find('M') != StringRef::npos);
+ }
+ bool supportsThumb2(StringRef ArchName, StringRef CPUArch,
+ unsigned CPUArchVer) const {
+ // We check both CPUArchVer and ArchName because when only triple is
+ // specified, the default CPU is arm1136j-s.
+ return ArchName.endswith("v6t2") || ArchName.endswith("v7") ||
+ ArchName.endswith("v8.1a") ||
+ ArchName.endswith("v8") || CPUArch == "6T2" || CPUArchVer >= 7;
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
- StringRef CPUAttr = getCPUAttr();
- StringRef CPUProfile = getCPUProfile();
-
// Target identification.
Builder.defineMacro("__arm");
Builder.defineMacro("__arm__");
@@ -4429,12 +4511,19 @@ public:
// Target properties.
Builder.defineMacro("__REGISTER_PREFIX__", "");
- Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
+ StringRef CPUArch = getCPUDefineSuffix(CPU);
+ unsigned int CPUArchVer;
+ if (CPUArch.substr(0, 1).getAsInteger<unsigned int>(10, CPUArchVer))
+ llvm_unreachable("Invalid char for architecture version number");
+ Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__");
// ACLE 6.4.1 ARM/Thumb instruction set architecture
+ StringRef CPUProfile = getCPUProfile(CPU);
+ StringRef ArchName = getTriple().getArchName();
+
// __ARM_ARCH is defined as an integer value indicating the current ARM ISA
- Builder.defineMacro("__ARM_ARCH", std::to_string(ArchVersion));
- if (ArchVersion >= 8) {
+ Builder.defineMacro("__ARM_ARCH", CPUArch.substr(0, 1));
+ if (CPUArch[0] >= '8') {
Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN");
Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING");
}
@@ -4448,9 +4537,9 @@ public:
// __ARM_ARCH_ISA_THUMB is defined to 1 if the core supporst the original
// Thumb ISA (including v6-M). It is set to 2 if the core supports the
// Thumb-2 ISA as found in the v6T2 architecture and all v7 architecture.
- if (supportsThumb2(CPUAttr))
+ if (supportsThumb2(ArchName, CPUArch, CPUArchVer))
Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
- else if (supportsThumb(CPUAttr))
+ else if (supportsThumb(ArchName, CPUArch, CPUArchVer))
Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
// __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
@@ -4475,7 +4564,7 @@ public:
// FIXME: It's more complicated than this and we don't really support
// interworking.
// Windows on ARM does not "support" interworking
- if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
+ if (5 <= CPUArchVer && CPUArchVer <= 8 && !getTriple().isOSWindows())
Builder.defineMacro("__THUMB_INTERWORK__");
if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
@@ -4498,7 +4587,7 @@ public:
if (IsThumb) {
Builder.defineMacro("__THUMBEL__");
Builder.defineMacro("__thumb__");
- if (supportsThumb2(CPUAttr))
+ if (supportsThumb2(ArchName, CPUArch, CPUArchVer))
Builder.defineMacro("__thumb2__");
}
if (((HWDiv & HWDivThumb) && IsThumb) || ((HWDiv & HWDivARM) && !IsThumb))
@@ -4521,7 +4610,7 @@ public:
// the VFP define, hence the soft float and arch check. This is subtly
// different from gcc, we follow the intent which was that it should be set
// when Neon instructions are actually available.
- if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
+ if ((FPU & NeonFPU) && !SoftFloat && CPUArchVer >= 7) {
Builder.defineMacro("__ARM_NEON");
Builder.defineMacro("__ARM_NEON__");
}
@@ -4538,18 +4627,18 @@ public:
if (Crypto)
Builder.defineMacro("__ARM_FEATURE_CRYPTO");
- if (ArchVersion >= 6 && CPUAttr != "6M") {
+ if (CPUArchVer >= 6 && CPUArch != "6M") {
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
- bool is5EOrAbove = (ArchVersion >= 6 ||
- (ArchVersion == 5 && CPUAttr.count('E')));
- // FIXME: We are not getting all 32-bit ARM architectures
- bool is32Bit = (!IsThumb || supportsThumb2(CPUAttr));
- if (is5EOrAbove && is32Bit && (CPUProfile != "M" || CPUAttr == "7EM"))
+ bool is5EOrAbove = (CPUArchVer >= 6 ||
+ (CPUArchVer == 5 &&
+ CPUArch.find('E') != StringRef::npos));
+ bool is32Bit = (!IsThumb || supportsThumb2(ArchName, CPUArch, CPUArchVer));
+ if (is5EOrAbove && is32Bit && (CPUProfile != "M" || CPUArch == "7EM"))
Builder.defineMacro("__ARM_FEATURE_DSP");
}
void getTargetBuiltins(const Builtin::Info *&Records,
@@ -6632,6 +6721,19 @@ void PNaClTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
NumAliases = 0;
}
+// We attempt to use PNaCl (le32) frontend and Mips32EL backend.
+class NaClMips32ELTargetInfo : public Mips32ELTargetInfo {
+public:
+ NaClMips32ELTargetInfo(const llvm::Triple &Triple) :
+ Mips32ELTargetInfo(Triple) {
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
+ }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::PNaClABIBuiltinVaList;
+ }
+};
+
class Le64TargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
@@ -7002,7 +7104,7 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<Mips32ELTargetInfo>(Triple);
case llvm::Triple::NaCl:
- return new NaClTargetInfo<Mips32ELTargetInfo>(Triple);
+ return new NaClTargetInfo<NaClMips32ELTargetInfo>(Triple);
default:
return new Mips32ELTargetInfo(Triple);
}
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 0bccad0570da..afcb9e5c5055 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -292,6 +292,7 @@ void EmitAssemblyHelper::CreatePasses() {
PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime;
PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops;
PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions;
+ PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO;
PMBuilder.RerollLoops = CodeGenOpts.RerollLoops;
PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
@@ -454,8 +455,6 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
BackendArgs.push_back("-limit-float-precision");
BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
}
- if (llvm::TimePassesIsEnabled)
- BackendArgs.push_back("-time-passes");
for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i)
BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str());
BackendArgs.push_back(nullptr);
diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index da82249fe114..9839617c0e41 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -93,6 +93,7 @@ namespace {
BFI = OrigBFI;
BFI.Offset = Offset;
BFI.StorageSize = AtomicSizeInBits;
+ BFI.StorageOffset += OffsetInChars;
LVal = LValue::MakeBitfield(Addr, BFI, lvalue.getType(),
lvalue.getAlignment());
LVal.setTBAAInfo(lvalue.getTBAAInfo());
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 2ec909b9aac5..9e538703177d 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -535,7 +535,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BI__builtin_readcyclecounter: {
Value *F = CGM.getIntrinsic(Intrinsic::readcyclecounter);
- return RValue::get(Builder.CreateCall(F, {}));
+ return RValue::get(Builder.CreateCall(F));
}
case Builtin::BI__builtin___clear_cache: {
Value *Begin = EmitScalarExpr(E->getArg(0));
@@ -923,7 +923,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BI__builtin_unwind_init: {
Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init);
- return RValue::get(Builder.CreateCall(F, {}));
+ return RValue::get(Builder.CreateCall(F));
}
case Builtin::BI__builtin_extend_pointer: {
// Extends a pointer to the size of an _Unwind_Word, which is
@@ -962,7 +962,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Store the stack pointer to the setjmp buffer.
Value *StackAddr =
- Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave), {});
+ Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave));
Value *StackSaveSlot =
Builder.CreateGEP(Buf, ConstantInt::get(Int32Ty, 2));
Builder.CreateStore(StackAddr, StackSaveSlot);
@@ -3399,7 +3399,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
: InlineAsm::get(FTy, ".inst 0x" + utohexstr(ZExtValue), "",
/*SideEffects=*/true);
- return Builder.CreateCall(Emit, {});
+ return Builder.CreateCall(Emit);
}
if (BuiltinID == ARM::BI__builtin_arm_dbg) {
@@ -3543,7 +3543,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
if (BuiltinID == ARM::BI__builtin_arm_clrex) {
Function *F = CGM.getIntrinsic(Intrinsic::arm_clrex);
- return Builder.CreateCall(F, {});
+ return Builder.CreateCall(F);
}
// CRC32
@@ -4339,7 +4339,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
if (BuiltinID == AArch64::BI__builtin_arm_clrex) {
Function *F = CGM.getIntrinsic(Intrinsic::aarch64_clrex);
- return Builder.CreateCall(F, {});
+ return Builder.CreateCall(F);
}
// CRC32
@@ -6375,7 +6375,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
break;
}
- Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID), {});
+ Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID));
Builder.CreateStore(Builder.CreateExtractValue(Call, 0), Ops[0]);
return Builder.CreateExtractValue(Call, 1);
}
@@ -6633,14 +6633,104 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
llvm::Function *F = CGM.getIntrinsic(ID);
return Builder.CreateCall(F, Ops, "");
}
+ // Square root
+ case PPC::BI__builtin_vsx_xvsqrtsp:
+ case PPC::BI__builtin_vsx_xvsqrtdp: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ ID = Intrinsic::sqrt;
+ llvm::Function *F = CGM.getIntrinsic(ID, ResultType);
+ return Builder.CreateCall(F, X);
+ }
+ // Count leading zeros
+ case PPC::BI__builtin_altivec_vclzb:
+ case PPC::BI__builtin_altivec_vclzh:
+ case PPC::BI__builtin_altivec_vclzw:
+ case PPC::BI__builtin_altivec_vclzd: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);
+ Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType);
+ return Builder.CreateCall(F, {X, Undef});
+ }
+ // Copy sign
+ case PPC::BI__builtin_vsx_xvcpsgnsp:
+ case PPC::BI__builtin_vsx_xvcpsgndp: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Value *Y = EmitScalarExpr(E->getArg(1));
+ ID = Intrinsic::copysign;
+ llvm::Function *F = CGM.getIntrinsic(ID, ResultType);
+ return Builder.CreateCall(F, {X, Y});
+ }
+ // Rounding/truncation
case PPC::BI__builtin_vsx_xvrspip:
case PPC::BI__builtin_vsx_xvrdpip:
+ case PPC::BI__builtin_vsx_xvrdpim:
+ case PPC::BI__builtin_vsx_xvrspim:
+ case PPC::BI__builtin_vsx_xvrdpi:
+ case PPC::BI__builtin_vsx_xvrspi:
+ case PPC::BI__builtin_vsx_xvrdpic:
+ case PPC::BI__builtin_vsx_xvrspic:
+ case PPC::BI__builtin_vsx_xvrdpiz:
+ case PPC::BI__builtin_vsx_xvrspiz: {
llvm::Type *ResultType = ConvertType(E->getType());
Value *X = EmitScalarExpr(E->getArg(0));
- ID = Intrinsic::ceil;
+ if (BuiltinID == PPC::BI__builtin_vsx_xvrdpim ||
+ BuiltinID == PPC::BI__builtin_vsx_xvrspim)
+ ID = Intrinsic::floor;
+ else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpi ||
+ BuiltinID == PPC::BI__builtin_vsx_xvrspi)
+ ID = Intrinsic::round;
+ else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpic ||
+ BuiltinID == PPC::BI__builtin_vsx_xvrspic)
+ ID = Intrinsic::nearbyint;
+ else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpip ||
+ BuiltinID == PPC::BI__builtin_vsx_xvrspip)
+ ID = Intrinsic::ceil;
+ else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpiz ||
+ BuiltinID == PPC::BI__builtin_vsx_xvrspiz)
+ ID = Intrinsic::trunc;
llvm::Function *F = CGM.getIntrinsic(ID, ResultType);
return Builder.CreateCall(F, X);
}
+ // FMA variations
+ case PPC::BI__builtin_vsx_xvmaddadp:
+ case PPC::BI__builtin_vsx_xvmaddasp:
+ case PPC::BI__builtin_vsx_xvnmaddadp:
+ case PPC::BI__builtin_vsx_xvnmaddasp:
+ case PPC::BI__builtin_vsx_xvmsubadp:
+ case PPC::BI__builtin_vsx_xvmsubasp:
+ case PPC::BI__builtin_vsx_xvnmsubadp:
+ case PPC::BI__builtin_vsx_xvnmsubasp: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Value *Y = EmitScalarExpr(E->getArg(1));
+ Value *Z = EmitScalarExpr(E->getArg(2));
+ Value *Zero = llvm::ConstantFP::getZeroValueForNegation(ResultType);
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);
+ switch (BuiltinID) {
+ case PPC::BI__builtin_vsx_xvmaddadp:
+ case PPC::BI__builtin_vsx_xvmaddasp:
+ return Builder.CreateCall(F, {X, Y, Z});
+ case PPC::BI__builtin_vsx_xvnmaddadp:
+ case PPC::BI__builtin_vsx_xvnmaddasp:
+ return Builder.CreateFSub(Zero,
+ Builder.CreateCall(F, {X, Y, Z}), "sub");
+ case PPC::BI__builtin_vsx_xvmsubadp:
+ case PPC::BI__builtin_vsx_xvmsubasp:
+ return Builder.CreateCall(F,
+ {X, Y, Builder.CreateFSub(Zero, Z, "sub")});
+ case PPC::BI__builtin_vsx_xvnmsubadp:
+ case PPC::BI__builtin_vsx_xvnmsubasp:
+ Value *FsubRes =
+ Builder.CreateCall(F, {X, Y, Builder.CreateFSub(Zero, Z, "sub")});
+ return Builder.CreateFSub(Zero, FsubRes, "sub");
+ }
+ llvm_unreachable("Unknown FMA operation");
+ return nullptr; // Suppress no-return warning
+ }
+ }
}
// Emit an intrinsic that has 1 float or double.
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 0535c05da5d5..3e4d7f323d46 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -912,20 +912,21 @@ static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val,
/// CreateCoercedLoad - Create a load from \arg SrcPtr interpreted as
-/// a pointer to an object of type \arg Ty.
+/// a pointer to an object of type \arg Ty, known to be aligned to
+/// \arg SrcAlign bytes.
///
/// This safely handles the case when the src type is smaller than the
/// destination type; in this situation the values of bits which not
/// present in the src are undefined.
static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
- llvm::Type *Ty,
+ llvm::Type *Ty, CharUnits SrcAlign,
CodeGenFunction &CGF) {
llvm::Type *SrcTy =
cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
// If SrcTy and Ty are the same, just do a load.
if (SrcTy == Ty)
- return CGF.Builder.CreateLoad(SrcPtr);
+ return CGF.Builder.CreateAlignedLoad(SrcPtr, SrcAlign.getQuantity());
uint64_t DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
@@ -940,7 +941,8 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
// extension or truncation to the desired type.
if ((isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) &&
(isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy))) {
- llvm::LoadInst *Load = CGF.Builder.CreateLoad(SrcPtr);
+ llvm::LoadInst *Load =
+ CGF.Builder.CreateAlignedLoad(SrcPtr, SrcAlign.getQuantity());
return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF);
}
@@ -954,23 +956,20 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
// to that information.
llvm::Value *Casted =
CGF.Builder.CreateBitCast(SrcPtr, llvm::PointerType::getUnqual(Ty));
- llvm::LoadInst *Load = CGF.Builder.CreateLoad(Casted);
- // FIXME: Use better alignment / avoid requiring aligned load.
- Load->setAlignment(1);
- return Load;
+ return CGF.Builder.CreateAlignedLoad(Casted, SrcAlign.getQuantity());
}
// Otherwise do coercion through memory. This is stupid, but
// simple.
- llvm::Value *Tmp = CGF.CreateTempAlloca(Ty);
+ llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(Ty);
+ Tmp->setAlignment(SrcAlign.getQuantity());
llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy();
llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy);
llvm::Value *SrcCasted = CGF.Builder.CreateBitCast(SrcPtr, I8PtrTy);
- // FIXME: Use better alignment.
CGF.Builder.CreateMemCpy(Casted, SrcCasted,
llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize),
- 1, false);
- return CGF.Builder.CreateLoad(Tmp);
+ SrcAlign.getQuantity(), false);
+ return CGF.Builder.CreateAlignedLoad(Tmp, SrcAlign.getQuantity());
}
// Function to store a first-class aggregate into memory. We prefer to
@@ -979,39 +978,45 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
// FIXME: Do we need to recurse here?
static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val,
llvm::Value *DestPtr, bool DestIsVolatile,
- bool LowAlignment) {
+ CharUnits DestAlign) {
// Prefer scalar stores to first-class aggregate stores.
if (llvm::StructType *STy =
dyn_cast<llvm::StructType>(Val->getType())) {
+ const llvm::StructLayout *Layout =
+ CGF.CGM.getDataLayout().getStructLayout(STy);
+
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
llvm::Value *EltPtr = CGF.Builder.CreateConstGEP2_32(STy, DestPtr, 0, i);
llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i);
- llvm::StoreInst *SI = CGF.Builder.CreateStore(Elt, EltPtr,
- DestIsVolatile);
- if (LowAlignment)
- SI->setAlignment(1);
+ uint64_t EltOffset = Layout->getElementOffset(i);
+ CharUnits EltAlign =
+ DestAlign.alignmentAtOffset(CharUnits::fromQuantity(EltOffset));
+ CGF.Builder.CreateAlignedStore(Elt, EltPtr, EltAlign.getQuantity(),
+ DestIsVolatile);
}
} else {
- llvm::StoreInst *SI = CGF.Builder.CreateStore(Val, DestPtr, DestIsVolatile);
- if (LowAlignment)
- SI->setAlignment(1);
+ CGF.Builder.CreateAlignedStore(Val, DestPtr, DestAlign.getQuantity(),
+ DestIsVolatile);
}
}
/// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src,
-/// where the source and destination may have different types.
+/// where the source and destination may have different types. The
+/// destination is known to be aligned to \arg DstAlign bytes.
///
/// This safely handles the case when the src type is larger than the
/// destination type; the upper bits of the src will be lost.
static void CreateCoercedStore(llvm::Value *Src,
llvm::Value *DstPtr,
bool DstIsVolatile,
+ CharUnits DstAlign,
CodeGenFunction &CGF) {
llvm::Type *SrcTy = Src->getType();
llvm::Type *DstTy =
cast<llvm::PointerType>(DstPtr->getType())->getElementType();
if (SrcTy == DstTy) {
- CGF.Builder.CreateStore(Src, DstPtr, DstIsVolatile);
+ CGF.Builder.CreateAlignedStore(Src, DstPtr, DstAlign.getQuantity(),
+ DstIsVolatile);
return;
}
@@ -1027,7 +1032,8 @@ static void CreateCoercedStore(llvm::Value *Src,
if ((isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy)) &&
(isa<llvm::IntegerType>(DstTy) || isa<llvm::PointerType>(DstTy))) {
Src = CoerceIntOrPtrToIntOrPtr(Src, DstTy, CGF);
- CGF.Builder.CreateStore(Src, DstPtr, DstIsVolatile);
+ CGF.Builder.CreateAlignedStore(Src, DstPtr, DstAlign.getQuantity(),
+ DstIsVolatile);
return;
}
@@ -1037,8 +1043,7 @@ static void CreateCoercedStore(llvm::Value *Src,
if (SrcSize <= DstSize) {
llvm::Value *Casted =
CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
- // FIXME: Use better alignment / avoid requiring aligned store.
- BuildAggStore(CGF, Src, Casted, DstIsVolatile, true);
+ BuildAggStore(CGF, Src, Casted, DstIsVolatile, DstAlign);
} else {
// Otherwise do coercion through memory. This is stupid, but
// simple.
@@ -1049,15 +1054,15 @@ static void CreateCoercedStore(llvm::Value *Src,
//
// FIXME: Assert that we aren't truncating non-padding bits when have access
// to that information.
- llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy);
- CGF.Builder.CreateStore(Src, Tmp);
+ llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(SrcTy);
+ Tmp->setAlignment(DstAlign.getQuantity());
+ CGF.Builder.CreateAlignedStore(Src, Tmp, DstAlign.getQuantity());
llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy();
llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy);
llvm::Value *DstCasted = CGF.Builder.CreateBitCast(DstPtr, I8PtrTy);
- // FIXME: Use better alignment.
CGF.Builder.CreateMemCpy(DstCasted, Casted,
llvm::ConstantInt::get(CGF.IntPtrTy, DstSize),
- 1, false);
+ DstAlign.getQuantity(), false);
}
}
@@ -1506,7 +1511,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl);
if (FD) {
- if (const TargetAttr *TD = FD->getAttr<TargetAttr>()) {
+ if (const auto *TD = FD->getAttr<TargetAttr>()) {
StringRef FeaturesStr = TD->getFeatures();
SmallVector<StringRef, 1> AttrFeatures;
FeaturesStr.split(AttrFeatures, ",");
@@ -1514,9 +1519,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// Grab the various features and prepend a "+" to turn on the feature to
// the backend and add them to our existing set of features.
for (auto &Feature : AttrFeatures) {
+ // Go ahead and trim whitespace rather than either erroring or
+ // accepting it weirdly.
+ Feature = Feature.trim();
+
// While we're here iterating check for a different target cpu.
if (Feature.startswith("arch="))
- TargetCPU = Feature.split("=").second;
+ TargetCPU = Feature.split("=").second.trim();
else if (Feature.startswith("tune="))
// We don't support cpu tuning this way currently.
;
@@ -1992,6 +2001,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
Alloca->setAlignment(AlignmentToUse);
llvm::Value *V = Alloca;
llvm::Value *Ptr = V; // Pointer to store into.
+ CharUnits PtrAlign = CharUnits::fromQuantity(AlignmentToUse);
// If the value is offset in memory, apply the offset now.
if (unsigned Offs = ArgI.getDirectOffset()) {
@@ -1999,6 +2009,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
Ptr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), Ptr, Offs);
Ptr = Builder.CreateBitCast(Ptr,
llvm::PointerType::getUnqual(ArgI.getCoerceToType()));
+ PtrAlign = PtrAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs));
}
// Fast-isel and the optimizer generally like scalar values better than
@@ -2043,7 +2054,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
assert(NumIRArgs == 1);
auto AI = FnArgs[FirstIRArg];
AI->setName(Arg->getName() + ".coerce");
- CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, *this);
+ CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, PtrAlign, *this);
}
@@ -2411,15 +2422,17 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
}
} else {
llvm::Value *V = ReturnValue;
+ CharUnits Align = getContext().getTypeAlignInChars(RetTy);
// If the value is offset in memory, apply the offset now.
if (unsigned Offs = RetAI.getDirectOffset()) {
V = Builder.CreateBitCast(V, Builder.getInt8PtrTy());
V = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), V, Offs);
V = Builder.CreateBitCast(V,
llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
+ Align = Align.alignmentAtOffset(CharUnits::fromQuantity(Offs));
}
- RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this);
+ RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), Align, *this);
}
// In ARC, end functions that return a retainable type with a call
@@ -3282,12 +3295,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// FIXME: Avoid the conversion through memory if possible.
llvm::Value *SrcPtr;
+ CharUnits SrcAlign;
if (RV.isScalar() || RV.isComplex()) {
SrcPtr = CreateMemTemp(I->Ty, "coerce");
+ SrcAlign = TypeAlign;
LValue SrcLV = MakeAddrLValue(SrcPtr, I->Ty, TypeAlign);
EmitInitStoreOfNonAggregate(*this, RV, SrcLV);
- } else
+ } else {
SrcPtr = RV.getAggregateAddr();
+ // This alignment is guaranteed by EmitCallArg.
+ SrcAlign = TypeAlign;
+ }
// If the value is offset in memory, apply the offset now.
if (unsigned Offs = ArgInfo.getDirectOffset()) {
@@ -3295,7 +3313,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
SrcPtr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), SrcPtr, Offs);
SrcPtr = Builder.CreateBitCast(SrcPtr,
llvm::PointerType::getUnqual(ArgInfo.getCoerceToType()));
-
+ SrcAlign = SrcAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs));
}
// Fast-isel and the optimizer generally like scalar values better than
@@ -3334,7 +3352,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// In the simple case, just pass the coerced loaded value.
assert(NumIRArgs == 1);
IRCallArgs[FirstIRArg] =
- CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(), *this);
+ CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(),
+ SrcAlign, *this);
}
break;
@@ -3531,12 +3550,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case TEK_Aggregate: {
llvm::Value *DestPtr = ReturnValue.getValue();
bool DestIsVolatile = ReturnValue.isVolatile();
+ CharUnits DestAlign = getContext().getTypeAlignInChars(RetTy);
if (!DestPtr) {
DestPtr = CreateMemTemp(RetTy, "agg.tmp");
DestIsVolatile = false;
}
- BuildAggStore(*this, CI, DestPtr, DestIsVolatile, false);
+ BuildAggStore(*this, CI, DestPtr, DestIsVolatile, DestAlign);
return RValue::getAggregate(DestPtr);
}
case TEK_Scalar: {
@@ -3553,6 +3573,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::Value *DestPtr = ReturnValue.getValue();
bool DestIsVolatile = ReturnValue.isVolatile();
+ CharUnits DestAlign = getContext().getTypeAlignInChars(RetTy);
if (!DestPtr) {
DestPtr = CreateMemTemp(RetTy, "coerce");
@@ -3561,14 +3582,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the value is offset in memory, apply the offset now.
llvm::Value *StorePtr = DestPtr;
+ CharUnits StoreAlign = DestAlign;
if (unsigned Offs = RetAI.getDirectOffset()) {
StorePtr = Builder.CreateBitCast(StorePtr, Builder.getInt8PtrTy());
StorePtr =
Builder.CreateConstGEP1_32(Builder.getInt8Ty(), StorePtr, Offs);
StorePtr = Builder.CreateBitCast(StorePtr,
llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
+ StoreAlign =
+ StoreAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs));
}
- CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this);
+ CreateCoercedStore(CI, StorePtr, DestIsVolatile, StoreAlign, *this);
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
}
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 62df9820a6c3..c49f182c21d8 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -554,6 +554,20 @@ static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) {
return false;
}
+static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF,
+ CXXCtorInitializer *MemberInit,
+ LValue &LHS) {
+ FieldDecl *Field = MemberInit->getAnyMember();
+ if (MemberInit->isIndirectMemberInitializer()) {
+ // If we are initializing an anonymous union field, drill down to the field.
+ IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember();
+ for (const auto *I : IndirectField->chain())
+ LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I));
+ } else {
+ LHS = CGF.EmitLValueForFieldInitialization(LHS, Field);
+ }
+}
+
static void EmitMemberInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXCtorInitializer *MemberInit,
@@ -572,16 +586,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
- if (MemberInit->isIndirectMemberInitializer()) {
- // If we are initializing an anonymous union field, drill down to
- // the field.
- IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember();
- for (const auto *I : IndirectField->chain())
- LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I));
- FieldType = MemberInit->getIndirectMember()->getAnonField()->getType();
- } else {
- LHS = CGF.EmitLValueForFieldInitialization(LHS, Field);
- }
+ EmitLValueForAnyFieldInitialization(CGF, MemberInit, LHS);
// Special case: if we are in a copy or move constructor, and we are copying
// an array of PODs or classes with trivial copy constructors, ignore the
@@ -606,6 +611,11 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
// Copy the aggregate.
CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType,
LHS.isVolatileQualified());
+ // Ensure that we destroy the objects if an exception is thrown later in
+ // the constructor.
+ QualType::DestructionKind dtorKind = FieldType.isDestructedType();
+ if (CGF.needsEHCleanup(dtorKind))
+ CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
return;
}
}
@@ -906,32 +916,18 @@ namespace {
return;
}
- CharUnits Alignment;
-
uint64_t FirstByteOffset;
if (FirstField->isBitField()) {
const CGRecordLayout &RL =
CGF.getTypes().getCGRecordLayout(FirstField->getParent());
const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField);
- Alignment = CharUnits::fromQuantity(BFInfo.StorageAlignment);
// FirstFieldOffset is not appropriate for bitfields,
- // it won't tell us what the storage offset should be and thus might not
- // be properly aligned.
- //
- // Instead calculate the storage offset using the offset of the field in
- // the struct type.
- const llvm::DataLayout &DL = CGF.CGM.getDataLayout();
- FirstByteOffset =
- DL.getStructLayout(RL.getLLVMType())
- ->getElementOffsetInBits(RL.getLLVMFieldNo(FirstField));
+ // we need to use the storage offset instead.
+ FirstByteOffset = CGF.getContext().toBits(BFInfo.StorageOffset);
} else {
- Alignment = CGF.getContext().getDeclAlign(FirstField);
FirstByteOffset = FirstFieldOffset;
}
- assert((CGF.getContext().toCharUnitsFromBits(FirstByteOffset) %
- Alignment) == 0 && "Bad field alignment.");
-
CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
llvm::Value *ThisPtr = CGF.LoadCXXThis();
@@ -941,6 +937,9 @@ namespace {
LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField);
+ CharUnits Offset = CGF.getContext().toCharUnitsFromBits(FirstByteOffset);
+ CharUnits Alignment = DestLV.getAlignment().alignmentAtOffset(Offset);
+
emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddr() : Dest.getAddress(),
Src.isBitField() ? Src.getBitFieldAddr() : Src.getAddress(),
MemcpySize, Alignment);
@@ -1078,6 +1077,7 @@ namespace {
CopyingValueRepresentation CVR(CGF);
EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
AggregatedInits[0], ConstructorDecl, Args);
+ AggregatedInits.clear();
}
reset();
return;
@@ -1094,10 +1094,14 @@ namespace {
LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
- QualType FieldType = AggregatedInits[i]->getMember()->getType();
+ CXXCtorInitializer *MemberInit = AggregatedInits[i];
+ QualType FieldType = MemberInit->getAnyMember()->getType();
QualType::DestructionKind dtorKind = FieldType.isDestructedType();
- if (CGF.needsEHCleanup(dtorKind))
- CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
+ if (!CGF.needsEHCleanup(dtorKind))
+ continue;
+ LValue FieldLHS = LHS;
+ EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS);
+ CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);
}
}
@@ -1363,6 +1367,25 @@ static bool CanSkipVTablePointerInitialization(ASTContext &Context,
return true;
}
+// Generates function call for handling object poisoning, passing in
+// references to 'this' and its size as arguments.
+static void EmitDtorSanitizerCallback(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor) {
+ const ASTRecordLayout &Layout =
+ CGF.getContext().getASTRecordLayout(Dtor->getParent());
+
+ llvm::Value *Args[] = {
+ CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.VoidPtrTy),
+ llvm::ConstantInt::get(CGF.SizeTy, Layout.getSize().getQuantity())};
+ llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy};
+
+ llvm::FunctionType *FnType =
+ llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
+ llvm::Value *Fn =
+ CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback");
+ CGF.EmitNounwindRuntimeCall(Fn, Args);
+}
+
/// EmitDestructorBody - Emits the body of the current destructor.
void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
@@ -1450,6 +1473,10 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// Exit the try if applicable.
if (isTryBody)
ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
+
+ // Insert memory-poisoning instrumentation.
+ if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor)
+ EmitDtorSanitizerCallback(*this, Dtor);
}
void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) {
@@ -2202,8 +2229,7 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
llvm::Value *VTable,
CFITypeCheckKind TCK,
SourceLocation Loc) {
- // FIXME: Add blacklisting scheme.
- if (RD->isInStdNamespace())
+ if (CGM.IsCFIBlacklistedRecord(RD))
return;
SanitizerScope SanScope(this);
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 8c4b4b3d0617..93a2287b1e01 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -106,8 +106,6 @@ ApplyDebugLocation::~ApplyDebugLocation() {
CGF.Builder.SetCurrentDebugLocation(std::move(OriginalLocation));
}
-/// ArtificialLocation - An RAII object that temporarily switches to
-/// an artificial debug location that has a valid scope, but no line
void CGDebugInfo::setLocation(SourceLocation Loc) {
// If the new location isn't valid return.
if (Loc.isInvalid())
@@ -140,7 +138,6 @@ void CGDebugInfo::setLocation(SourceLocation Loc) {
}
}
-/// getContextDescriptor - Get context info for the decl.
llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context) {
if (!Context)
return TheCU;
@@ -162,9 +159,6 @@ llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context) {
return TheCU;
}
-/// getFunctionName - Get function name for the given FunctionDecl. If the
-/// name is constructed on demand (e.g. C++ destructor) then the name
-/// is stored on the side.
StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
assert(FD && "Invalid FunctionDecl!");
IdentifierInfo *FII = FD->getIdentifier();
@@ -220,13 +214,10 @@ StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
return internString(OS.str());
}
-/// getSelectorName - Return selector name. This is used for debugging
-/// info.
StringRef CGDebugInfo::getSelectorName(Selector S) {
return internString(S.getAsString());
}
-/// getClassName - Get class name including template argument list.
StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
// quick optimization to avoid having to intern strings that are already
// stored reliably elsewhere
@@ -244,7 +235,6 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
return internString(Name);
}
-/// getOrCreateFile - Get the file debug info descriptor for the input location.
llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
@@ -274,13 +264,10 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
return F;
}
-/// getOrCreateMainFile - Get the file info for main compile unit.
llvm::DIFile *CGDebugInfo::getOrCreateMainFile() {
return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
}
-/// getLineNumber - Get line number for the location. If location is invalid
-/// then use current location.
unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
if (Loc.isInvalid() && CurLoc.isInvalid())
return 0;
@@ -289,7 +276,6 @@ unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
return PLoc.isValid() ? PLoc.getLine() : 0;
}
-/// getColumnNumber - Get column number for the location.
unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) {
// We may not want column information at all.
if (!Force && !CGM.getCodeGenOpts().DebugColumnInfo)
@@ -314,7 +300,6 @@ StringRef CGDebugInfo::getCurrentDirname() {
return CWDName = internString(CWD);
}
-/// CreateCompileUnit - Create new compile unit.
void CGDebugInfo::CreateCompileUnit() {
// Should we be asking the SourceManager for the main file name, instead of
@@ -385,8 +370,6 @@ void CGDebugInfo::CreateCompileUnit() {
DebugKind != CodeGenOptions::LocTrackingOnly);
}
-/// CreateType - Get the Basic type from the cache or create a new
-/// one if necessary.
llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
llvm::dwarf::TypeKind Encoding;
StringRef BTName;
@@ -537,8 +520,6 @@ llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
return DBuilder.createBasicType("complex", Size, Align, Encoding);
}
-/// CreateCVRType - Get the qualified type from the cache or create
-/// a new one if necessary.
llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
llvm::DIFile *Unit) {
QualifierCollector Qc;
@@ -627,6 +608,7 @@ static SmallString<256> getUniqueTagTypeName(const TagType *Ty,
return FullName;
}
+/// \return the approproate DWARF tag for a composite type.
static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) {
llvm::dwarf::Tag Tag;
if (RD->isStruct() || RD->isInterface())
@@ -642,7 +624,6 @@ static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) {
return Tag;
}
-// Creates a forward declaration for a RecordDecl in the given context.
llvm::DICompositeType *
CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
llvm::DIScope *Ctx) {
@@ -705,9 +686,6 @@ llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
llvm::DIFile *Unit) {
- if (BlockLiteralGeneric)
- return BlockLiteralGeneric;
-
SmallVector<llvm::Metadata *, 8> EltTys;
QualType FType;
uint64_t FieldSize, FieldOffset;
@@ -723,10 +701,10 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
EltTys.clear();
unsigned Flags = llvm::DINode::FlagAppleBlock;
- unsigned LineNo = getLineNumber(CurLoc);
+ unsigned LineNo = 0;
auto *EltTy =
- DBuilder.createStructType(Unit, "__block_descriptor", Unit, LineNo,
+ DBuilder.createStructType(Unit, "__block_descriptor", nullptr, LineNo,
FieldOffset, 0, Flags, nullptr, Elements);
// Bit size, align and offset of the type.
@@ -746,19 +724,22 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
FieldSize = CGM.getContext().getTypeSize(Ty);
FieldAlign = CGM.getContext().getTypeAlign(Ty);
- EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", Unit, LineNo,
+ EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", nullptr, LineNo,
FieldSize, FieldAlign, FieldOffset,
0, DescTy));
FieldOffset += FieldSize;
Elements = DBuilder.getOrCreateArray(EltTys);
+ // The __block_literal_generic structs are marked with a special
+ // 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, "__block_literal_generic", Unit, LineNo,
+ DBuilder.createStructType(Unit, "", nullptr, LineNo,
FieldOffset, 0, Flags, nullptr, Elements);
- BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
- return BlockLiteralGeneric;
+ return DBuilder.createPointerType(EltTy, Size);
}
llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
@@ -871,7 +852,6 @@ llvm::DIType *CGDebugInfo::createFieldType(
AlignInBits, offsetInBits, flags, debugType);
}
-/// CollectRecordLambdaFields - Helper for CollectRecordFields.
void CGDebugInfo::CollectRecordLambdaFields(
const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements,
llvm::DIType *RecordTy) {
@@ -916,7 +896,6 @@ void CGDebugInfo::CollectRecordLambdaFields(
}
}
-/// Helper for CollectRecordFields.
llvm::DIDerivedType *
CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
const RecordDecl *RD) {
@@ -946,7 +925,6 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
return GV;
}
-/// CollectRecordNormalField - Helper for CollectRecordFields.
void CGDebugInfo::CollectRecordNormalField(
const FieldDecl *field, uint64_t OffsetInBits, llvm::DIFile *tunit,
SmallVectorImpl<llvm::Metadata *> &elements, llvm::DIType *RecordTy,
@@ -971,8 +949,6 @@ void CGDebugInfo::CollectRecordNormalField(
elements.push_back(fieldType);
}
-/// CollectRecordFields - A helper function to collect debug info for
-/// record fields. This is used while creating debug info entry for a Record.
void CGDebugInfo::CollectRecordFields(
const RecordDecl *record, llvm::DIFile *tunit,
SmallVectorImpl<llvm::Metadata *> &elements,
@@ -1011,9 +987,6 @@ void CGDebugInfo::CollectRecordFields(
}
}
-/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
-/// function type is not updated to include implicit "this" pointer. Use this
-/// routine to get a method type which includes "this" pointer.
llvm::DISubroutineType *
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile *Unit) {
@@ -1088,8 +1061,6 @@ static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
return false;
}
-/// CreateCXXMemberFunction - A helper function to create a subprogram for
-/// a single member function GlobalDecl.
llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
const CXXMethodDecl *Method, llvm::DIFile *Unit, llvm::DIType *RecordTy) {
bool IsCtorOrDtor =
@@ -1165,9 +1136,6 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
return SP;
}
-/// CollectCXXMemberFunctions - A helper function to collect debug info for
-/// C++ member functions. This is used while creating debug info entry for
-/// a Record.
void CGDebugInfo::CollectCXXMemberFunctions(
const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy) {
@@ -1206,9 +1174,6 @@ void CGDebugInfo::CollectCXXMemberFunctions(
}
}
-/// CollectCXXBases - A helper function to collect debug info for
-/// C++ base classes. This is used while creating debug info entry for
-/// a Record.
void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys,
llvm::DIType *RecordTy) {
@@ -1246,7 +1211,6 @@ void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
}
}
-/// CollectTemplateParams - A helper function to collect template parameters.
llvm::DINodeArray
CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
ArrayRef<TemplateArgument> TAList,
@@ -1351,8 +1315,6 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
return DBuilder.getOrCreateArray(TemplateParams);
}
-/// CollectFunctionTemplateParams - A helper function to collect debug
-/// info for function template parameters.
llvm::DINodeArray
CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
llvm::DIFile *Unit) {
@@ -1367,8 +1329,6 @@ CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
return llvm::DINodeArray();
}
-/// CollectCXXTemplateParams - A helper function to collect debug info for
-/// template parameters.
llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(
const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile *Unit) {
// Always get the full list of parameters, not just the ones from
@@ -1379,7 +1339,6 @@ llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(
return CollectTemplateParams(TPList, TAList.asArray(), Unit);
}
-/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) {
if (VTablePtrType)
return VTablePtrType;
@@ -1397,14 +1356,11 @@ llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) {
return VTablePtrType;
}
-/// getVTableName - Get vtable name for the given Class.
StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
// Copy the gdb compatible name on the side and use its reference.
return internString("_vptr$", RD->getNameAsString());
}
-/// CollectVTableInfo - If the C++ class has vtable info then insert appropriate
-/// debug info entry in EltTys vector.
void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys) {
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
@@ -1424,7 +1380,6 @@ void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
EltTys.push_back(VPTR);
}
-/// getOrCreateRecordType - Emit record type's standalone debug info.
llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy,
SourceLocation Loc) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@@ -1432,8 +1387,6 @@ llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy,
return T;
}
-/// getOrCreateInterfaceType - Emit an objective c interface type standalone
-/// debug info.
llvm::DIType *CGDebugInfo::getOrCreateInterfaceType(QualType D,
SourceLocation Loc) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@@ -1531,7 +1484,6 @@ static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind,
return false;
}
-/// CreateType - get structure or union type.
llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0)));
@@ -1605,7 +1557,6 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
return FwdDecl;
}
-/// CreateType - get objective-c object type.
llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty,
llvm::DIFile *Unit) {
// Ignore protocols.
@@ -1636,7 +1587,6 @@ static bool hasDefaultSetterName(const ObjCPropertyDecl *PD,
Setter->getDeclName().getObjCSelector().getNameForSlot(0);
}
-/// CreateType - get objective-c interface type.
llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::DIFile *Unit) {
ObjCInterfaceDecl *ID = Ty->getDecl();
@@ -1956,7 +1906,6 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
return getOrCreateType(Ty->getValueType(), U);
}
-/// CreateEnumType - get enumeration type.
llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
@@ -2076,8 +2025,6 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
} while (true);
}
-/// getType - Get the type from the cache or return null type if it doesn't
-/// exist.
llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) {
// Unwrap the type as needed for debug information.
@@ -2104,8 +2051,6 @@ void CGDebugInfo::completeTemplateDefinition(
RetainedTypes.push_back(CGM.getContext().getRecordType(&SD).getAsOpaquePtr());
}
-/// getOrCreateType - Get the type from the cache or create a new
-/// one if necessary.
llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
if (Ty.isNull())
return nullptr;
@@ -2126,8 +2071,6 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
return Res;
}
-/// Currently the checksum of an interface includes the number of
-/// ivars and property accessors.
unsigned CGDebugInfo::Checksum(const ObjCInterfaceDecl *ID) {
// The assumption is that the number of ivars can only increase
// monotonically, so it is safe to just use their current number as
@@ -2152,7 +2095,6 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) {
}
}
-/// CreateTypeNode - Create a new debug type node.
llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
// Handle qualifiers, which recursively handles what they refer to.
if (Ty.hasLocalQualifiers())
@@ -2233,8 +2175,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
llvm_unreachable("type should have been unwrapped!");
}
-/// getOrCreateLimitedType - Get the type from the cache or create a new
-/// limited type if necessary.
llvm::DIType *CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty,
llvm::DIFile *Unit) {
QualType QTy(Ty, 0);
@@ -2328,7 +2268,6 @@ void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD,
DBuilder.replaceVTableHolder(RealDecl, ContainingType);
}
-/// CreateMemberType - Create new member and increase Offset by FType's size.
llvm::DIType *CGDebugInfo::CreateMemberType(llvm::DIFile *Unit, QualType FType,
StringRef Name, uint64_t *Offset) {
llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
@@ -2493,8 +2432,6 @@ llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
return nullptr;
}
-/// getFunctionDeclaration - Return debug info descriptor to describe method
-/// declaration for the given method definition.
llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) {
if (!D || DebugKind <= CodeGenOptions::DebugLineTablesOnly)
return nullptr;
@@ -2591,7 +2528,6 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
}
-/// EmitFunctionStart - Constructs the debug code for entering a function.
void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
SourceLocation ScopeLoc, QualType FnType,
llvm::Function *Fn, CGBuilderTy &Builder) {
@@ -2667,9 +2603,6 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
RegionMap[D].reset(SP);
}
-/// EmitLocation - Emit metadata to indicate a change in line/column
-/// information in the source file. If the location is invalid, the
-/// previous location will be reused.
void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
// Update our current location
setLocation(Loc);
@@ -2682,8 +2615,6 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
getLineNumber(CurLoc), getColumnNumber(CurLoc), Scope));
}
-/// CreateLexicalBlock - Creates a new lexical block node and pushes it on
-/// the stack.
void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
llvm::MDNode *Back = nullptr;
if (!LexicalBlockStack.empty())
@@ -2693,8 +2624,6 @@ void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
getColumnNumber(CurLoc)));
}
-/// EmitLexicalBlockStart - Constructs the debug code for entering a declarative
-/// region - beginning of a DW_TAG_lexical_block.
void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder,
SourceLocation Loc) {
// Set our current location.
@@ -2711,8 +2640,6 @@ void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder,
CreateLexicalBlock(Loc);
}
-/// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative
-/// region - end of a DW_TAG_lexical_block.
void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder,
SourceLocation Loc) {
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
@@ -2726,7 +2653,6 @@ void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder,
LexicalBlockStack.pop_back();
}
-/// EmitFunctionEnd - Constructs the debug code for exiting a function.
void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
unsigned RCount = FnBeginRegionCount.back();
@@ -2741,8 +2667,6 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
FnBeginRegionCount.pop_back();
}
-// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
-// See BuildByRefType.
llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *XOffset) {
@@ -2816,7 +2740,6 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
nullptr, Elements);
}
-/// EmitDeclare - Emit local variable declaration debug info.
void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::Tag Tag,
llvm::Value *Storage, unsigned ArgNo,
CGBuilderTy &Builder) {
@@ -2944,12 +2867,6 @@ void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
}
-/// Look up the completed type for a self pointer in the TypeCache and
-/// create a copy of it with the ObjectPointer and Artificial flags
-/// set. If the type is not cached, a new one is created. This should
-/// never happen though, since creating a type for the implicit self
-/// argument implies that we already parsed the interface definition
-/// and the ivar declarations in the implementation.
llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy,
llvm::DIType *Ty) {
llvm::DIType *CachedTy = getTypeOrNull(QualTy);
@@ -3027,8 +2944,6 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
Builder.GetInsertBlock());
}
-/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
-/// variable declaration.
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
unsigned ArgNo,
CGBuilderTy &Builder) {
@@ -3192,8 +3107,6 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
Builder.GetInsertBlock());
}
-/// If D is an out-of-class definition of a static data member of a class, find
-/// its corresponding in-class declaration.
llvm::DIDerivedType *
CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
if (!D->isStaticDataMember())
@@ -3213,9 +3126,6 @@ CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC));
}
-/// Recursively collect all of the member fields of a global anonymous decl and
-/// create static variables for them. The first time this is called it needs
-/// to be on a union and then from there we can have additional unnamed fields.
llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls(
const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo,
StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext) {
@@ -3241,7 +3151,6 @@ llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls(
return GV;
}
-/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const VarDecl *D) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@@ -3274,7 +3183,6 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
DeclCache[D->getCanonicalDecl()].reset(static_cast<llvm::Metadata *>(GV));
}
-/// EmitGlobalVariable - Emit global variable's debug info.
void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
llvm::Constant *Init) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
@@ -3380,8 +3288,6 @@ CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) {
return R;
}
-/// getOrCreateNamesSpace - Return namespace descriptor for the given
-/// namespace decl.
llvm::DINamespace *
CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
NSDecl = NSDecl->getCanonicalDecl();
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 10d3b0d9ab02..4c77a8d28974 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -26,26 +26,26 @@
#include "llvm/Support/Allocator.h"
namespace llvm {
- class MDNode;
+class MDNode;
}
namespace clang {
- class CXXMethodDecl;
- class VarDecl;
- class ObjCInterfaceDecl;
- class ObjCIvarDecl;
- class ClassTemplateSpecializationDecl;
- class GlobalDecl;
- class UsingDecl;
+class CXXMethodDecl;
+class VarDecl;
+class ObjCInterfaceDecl;
+class ObjCIvarDecl;
+class ClassTemplateSpecializationDecl;
+class GlobalDecl;
+class UsingDecl;
namespace CodeGen {
- class CodeGenModule;
- class CodeGenFunction;
- class CGBlockInfo;
+class CodeGenModule;
+class CodeGenFunction;
+class CGBlockInfo;
-/// \brief This class gathers all debug information during compilation
-/// and is responsible for emitting to llvm globals or pass directly to
-/// the backend.
+/// This class gathers all debug information during compilation and is
+/// responsible for emitting to llvm globals or pass directly to the
+/// backend.
class CGDebugInfo {
friend class ApplyDebugLocation;
friend class SaveAndRestoreLocation;
@@ -65,9 +65,8 @@ class CGDebugInfo {
llvm::DIType *OCLImage2dArrayDITy = nullptr;
llvm::DIType *OCLImage3dDITy = nullptr;
llvm::DIType *OCLEventDITy = nullptr;
- llvm::DIType *BlockLiteralGeneric = nullptr;
- /// \brief Cache of previously constructed Types.
+ /// Cache of previously constructed Types.
llvm::DenseMap<const void *, llvm::TrackingMDRef> TypeCache;
struct ObjCInterfaceCacheEntry {
@@ -79,41 +78,40 @@ class CGDebugInfo {
: Type(Type), Decl(Decl), Unit(Unit) {}
};
- /// \brief Cache of previously constructed interfaces
- /// which may change.
+ /// Cache of previously constructed interfaces which may change.
llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache;
- /// \brief Cache of references to AST files such as PCHs or modules.
+ /// Cache of references to AST files such as PCHs or modules.
llvm::DenseMap<uint64_t, llvm::DIModule *> ModuleRefCache;
- /// \brief list of interfaces we want to keep even if orphaned.
+ /// List of interfaces we want to keep even if orphaned.
std::vector<void *> RetainedTypes;
- /// \brief Cache of forward declared types to RAUW at the end of
+ /// Cache of forward declared types to RAUW at the end of
/// compilation.
std::vector<std::pair<const TagType *, llvm::TrackingMDRef>> ReplaceMap;
- /// \brief Cache of replaceable forward declarartions (functions and
+ /// Cache of replaceable forward declarartions (functions and
/// variables) to RAUW at the end of compilation.
std::vector<std::pair<const DeclaratorDecl *, llvm::TrackingMDRef>>
FwdDeclReplaceMap;
- // LexicalBlockStack - Keep track of our current nested lexical block.
+ /// Keep track of our current nested lexical block.
std::vector<llvm::TypedTrackingMDRef<llvm::DIScope>> LexicalBlockStack;
llvm::DenseMap<const Decl *, llvm::TrackingMDRef> RegionMap;
- // FnBeginRegionCount - Keep track of LexicalBlockStack counter at the
- // beginning of a function. This is used to pop unbalanced regions at
- // the end of a function.
+ /// Keep track of LexicalBlockStack counter at the beginning of a
+ /// function. This is used to pop unbalanced regions at the end of a
+ /// function.
std::vector<unsigned> FnBeginRegionCount;
- /// \brief This is a storage for names that are
- /// constructed on demand. For example, C++ destructors, C++ operators etc..
+ /// This is a storage for names that are constructed on demand. For
+ /// example, C++ destructors, C++ operators etc..
llvm::BumpPtrAllocator DebugInfoNames;
StringRef CWDName;
llvm::DenseMap<const char *, llvm::TrackingMDRef> DIFileCache;
llvm::DenseMap<const FunctionDecl *, llvm::TrackingMDRef> SPCache;
- /// \brief Cache declarations relevant to DW_TAG_imported_declarations (C++
+ /// Cache declarations relevant to DW_TAG_imported_declarations (C++
/// using declarations) that aren't covered by other more specific caches.
llvm::DenseMap<const Decl *, llvm::TrackingMDRef> DeclCache;
llvm::DenseMap<const NamespaceDecl *, llvm::TrackingMDRef> NameSpaceCache;
@@ -122,6 +120,9 @@ class CGDebugInfo {
llvm::DenseMap<const Decl *, llvm::TrackingMDRef> StaticDataMemberCache;
/// Helper functions for getOrCreateType.
+ /// @{
+ /// Currently the checksum of an interface includes the number of
+ /// ivars and property accessors.
unsigned Checksum(const ObjCInterfaceDecl *InterfaceDecl);
llvm::DIType *CreateType(const BuiltinType *Ty);
llvm::DIType *CreateType(const ComplexType *Ty);
@@ -133,14 +134,17 @@ class CGDebugInfo {
llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const BlockPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F);
+ /// Get structure or union type.
llvm::DIType *CreateType(const RecordType *Tyg);
llvm::DIType *CreateTypeDefinition(const RecordType *Ty);
llvm::DICompositeType *CreateLimitedType(const RecordType *Ty);
void CollectContainingType(const CXXRecordDecl *RD,
llvm::DICompositeType *CT);
+ /// Get Objective-C interface type.
llvm::DIType *CreateType(const ObjCInterfaceType *Ty, llvm::DIFile *F);
llvm::DIType *CreateTypeDefinition(const ObjCInterfaceType *Ty,
llvm::DIFile *F);
+ /// Get Objective-C object type.
llvm::DIType *CreateType(const ObjCObjectType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const VectorType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const ArrayType *Ty, llvm::DIFile *F);
@@ -148,10 +152,25 @@ class CGDebugInfo {
llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit);
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
+ /// Get enumeration type.
llvm::DIType *CreateEnumType(const EnumType *Ty);
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
+ /// Look up the completed type for a self pointer in the TypeCache and
+ /// create a copy of it with the ObjectPointer and Artificial flags
+ /// set. If the type is not cached, a new one is created. This should
+ /// never happen though, since creating a type for the implicit self
+ /// argument implies that we already parsed the interface definition
+ /// and the ivar declarations in the implementation.
llvm::DIType *CreateSelfType(const QualType &QualTy, llvm::DIType *Ty);
+ /// @}
+
+ /// Get the type from the cache or return null type if it doesn't
+ /// exist.
llvm::DIType *getTypeOrNull(const QualType);
+ /// Return the debug type for a C++ method.
+ /// \arg CXXMethodDecl is of FunctionType. This function type is
+ /// not updated to include implicit \c this pointer. Use this routine
+ /// to get a method type which includes \c this pointer.
llvm::DISubroutineType *getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile *F);
llvm::DISubroutineType *
@@ -159,7 +178,9 @@ class CGDebugInfo {
llvm::DIFile *Unit);
llvm::DISubroutineType *
getOrCreateFunctionType(const Decl *D, QualType FnType, llvm::DIFile *F);
+ /// \return debug info descriptor for vtable.
llvm::DIType *getOrCreateVTablePtrType(llvm::DIFile *F);
+ /// \return namespace descriptor for the given namespace decl.
llvm::DINamespace *getOrCreateNameSpace(const NamespaceDecl *N);
llvm::DIType *getOrCreateTypeDeclaration(QualType PointeeTy, llvm::DIFile *F);
llvm::DIType *CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty,
@@ -168,23 +189,37 @@ class CGDebugInfo {
llvm::Value *getCachedInterfaceTypeOrNull(const QualType Ty);
llvm::DIType *getOrCreateStructPtrType(StringRef Name, llvm::DIType *&Cache);
+ /// A helper function to create a subprogram for a single member
+ /// function GlobalDecl.
llvm::DISubprogram *CreateCXXMemberFunction(const CXXMethodDecl *Method,
llvm::DIFile *F,
llvm::DIType *RecordTy);
+ /// A helper function to collect debug info for C++ member
+ /// functions. This is used while creating debug info entry for a
+ /// Record.
void CollectCXXMemberFunctions(const CXXRecordDecl *Decl, llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DIType *T);
+ /// A helper function to collect debug info for C++ base
+ /// classes. This is used while creating debug info entry for a
+ /// Record.
void CollectCXXBases(const CXXRecordDecl *Decl, llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &EltTys,
llvm::DIType *RecordTy);
+ /// A helper function to collect template parameters.
llvm::DINodeArray CollectTemplateParams(const TemplateParameterList *TPList,
ArrayRef<TemplateArgument> TAList,
llvm::DIFile *Unit);
+ /// A helper function to collect debug info for function template
+ /// parameters.
llvm::DINodeArray CollectFunctionTemplateParams(const FunctionDecl *FD,
llvm::DIFile *Unit);
+
+ /// A helper function to collect debug info for template
+ /// parameters.
llvm::DINodeArray
CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TS,
llvm::DIFile *F);
@@ -195,7 +230,8 @@ class CGDebugInfo {
llvm::DIFile *tunit, llvm::DIScope *scope,
const RecordDecl *RD = nullptr);
- // Helpers for collecting fields of a record.
+ /// Helpers for collecting fields of a record.
+ /// @{
void CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl,
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DIType *RecordTy);
@@ -210,11 +246,13 @@ class CGDebugInfo {
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DICompositeType *RecordTy);
+ /// If the C++ class has vtable info then insert appropriate debug
+ /// info entry in EltTys vector.
void CollectVTableInfo(const CXXRecordDecl *Decl, llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &EltTys);
+ /// @}
- // CreateLexicalBlock - Create a new lexical block node and push it on
- // the stack.
+ /// Create a new lexical block node and push it on the stack.
void CreateLexicalBlock(SourceLocation Loc);
public:
@@ -223,86 +261,84 @@ public:
void finalize();
- /// \brief Update the current source location. If \arg loc is
- /// invalid it is ignored.
+ /// Update the current source location. If \arg loc is invalid it is
+ /// ignored.
void setLocation(SourceLocation Loc);
- /// \brief Emit metadata to indicate a change in line/column
- /// information in the source file.
+ /// Emit metadata to indicate a change in line/column information in
+ /// the source file. If the location is invalid, the previous
+ /// location will be reused.
void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc);
- /// \brief Emit a call to llvm.dbg.function.start to indicate
+ /// Emit a call to llvm.dbg.function.start to indicate
/// start of a new function.
/// \param Loc The location of the function header.
/// \param ScopeLoc The location of the function body.
- void EmitFunctionStart(GlobalDecl GD,
- SourceLocation Loc, SourceLocation ScopeLoc,
- QualType FnType, llvm::Function *Fn,
- CGBuilderTy &Builder);
+ void EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
+ SourceLocation ScopeLoc, QualType FnType,
+ llvm::Function *Fn, CGBuilderTy &Builder);
- /// \brief Constructs the debug code for exiting a function.
+ /// Constructs the debug code for exiting a function.
void EmitFunctionEnd(CGBuilderTy &Builder);
- /// \brief Emit metadata to indicate the beginning of a
- /// new lexical block and push the block onto the stack.
+ /// Emit metadata to indicate the beginning of a new lexical block
+ /// and push the block onto the stack.
void EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc);
- /// \brief Emit metadata to indicate the end of a new lexical
- /// block and pop the current block.
+ /// Emit metadata to indicate the end of a new lexical block and pop
+ /// the current block.
void EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc);
- /// \brief Emit call to llvm.dbg.declare for an automatic
- /// variable declaration.
+ /// Emit call to \c llvm.dbg.declare for an automatic variable
+ /// declaration.
void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
CGBuilderTy &Builder);
- /// \brief Emit call to llvm.dbg.declare for an
- /// imported variable declaration in a block.
+ /// Emit call to \c llvm.dbg.declare for an imported variable
+ /// declaration in a block.
void EmitDeclareOfBlockDeclRefVariable(const VarDecl *variable,
llvm::Value *storage,
CGBuilderTy &Builder,
const CGBlockInfo &blockInfo,
llvm::Instruction *InsertPoint = 0);
- /// \brief Emit call to llvm.dbg.declare for an argument
- /// variable declaration.
+ /// Emit call to \c llvm.dbg.declare for an argument variable
+ /// declaration.
void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
unsigned ArgNo, CGBuilderTy &Builder);
- /// \brief Emit call to
- /// llvm.dbg.declare for the block-literal argument to a block
- /// invocation function.
+ /// Emit call to \c llvm.dbg.declare for the block-literal argument
+ /// to a block invocation function.
void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::Value *Arg, unsigned ArgNo,
llvm::Value *LocalAddr,
CGBuilderTy &Builder);
- /// \brief Emit information about a global variable.
+ /// Emit information about a global variable.
void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
- /// \brief Emit global variable's debug info.
+ /// Emit global variable's debug info.
void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init);
- /// \brief Emit C++ using directive.
+ /// Emit C++ using directive.
void EmitUsingDirective(const UsingDirectiveDecl &UD);
- /// \brief Emit the type explicitly casted to.
+ /// Emit the type explicitly casted to.
void EmitExplicitCastType(QualType Ty);
- /// \brief Emit C++ using declaration.
+ /// Emit C++ using declaration.
void EmitUsingDecl(const UsingDecl &UD);
- /// \brief Emit an @import declaration.
+ /// Emit an @import declaration.
void EmitImportDecl(const ImportDecl &ID);
- /// \brief Emit C++ namespace alias.
+ /// Emit C++ namespace alias.
llvm::DIImportedEntity *EmitNamespaceAlias(const NamespaceAliasDecl &NA);
- /// \brief Emit record type's standalone debug info.
+ /// Emit record type's standalone debug info.
llvm::DIType *getOrCreateRecordType(QualType Ty, SourceLocation L);
- /// \brief Emit an objective c interface type standalone
- /// debug info.
+ /// Emit an Objective-C interface type standalone debug info.
llvm::DIType *getOrCreateInterfaceType(QualType Ty, SourceLocation Loc);
void completeType(const EnumDecl *ED);
@@ -313,120 +349,124 @@ public:
void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD);
private:
- /// \brief Emit call to llvm.dbg.declare for a variable declaration.
+ /// Emit call to llvm.dbg.declare for a variable declaration.
/// Tag accepts custom types DW_TAG_arg_variable and DW_TAG_auto_variable,
/// otherwise would be of type llvm::dwarf::Tag.
void EmitDeclare(const VarDecl *decl, llvm::dwarf::Tag Tag, llvm::Value *AI,
unsigned ArgNo, CGBuilderTy &Builder);
- // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
- // See BuildByRefType.
+ /// Build up structure info for the byref. See \a BuildByRefType.
llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *OffSet);
- /// \brief Get context info for the decl.
+ /// Get context info for the decl.
llvm::DIScope *getContextDescriptor(const Decl *Decl);
llvm::DIScope *getCurrentContextDescriptor(const Decl *Decl);
- /// \brief Create a forward decl for a RecordType in a given context.
+ /// Create a forward decl for a RecordType in a given context.
llvm::DICompositeType *getOrCreateRecordFwdDecl(const RecordType *,
llvm::DIScope *);
- /// \brief Return current directory name.
+ /// Return current directory name.
StringRef getCurrentDirname();
- /// \brief Create new compile unit.
+ /// Create new compile unit.
void CreateCompileUnit();
- /// \brief Get the file debug info descriptor for the input
- /// location.
+ /// Get the file debug info descriptor for the input location.
llvm::DIFile *getOrCreateFile(SourceLocation Loc);
- /// \brief Get the file info for main compile unit.
+ /// Get the file info for main compile unit.
llvm::DIFile *getOrCreateMainFile();
- /// \brief Get the type from the cache or create a new type if
- /// necessary.
+ /// Get the type from the cache or create a new type if necessary.
llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg);
- /// \brief Get a reference to a clang module.
+ /// Get a reference to a clang module.
llvm::DIModule *
getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod);
- /// \brief Get the type from the cache or create a new
- /// partial type if necessary.
+ /// Get the type from the cache or create a new partial type if
+ /// necessary.
llvm::DIType *getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile *F);
- /// \brief Create type metadata for a source language type.
+ /// Create type metadata for a source language type.
llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg);
- /// \brief return the underlying ObjCInterfaceDecl
- /// if Ty is an ObjCInterface or a pointer to one.
- ObjCInterfaceDecl* getObjCInterfaceDecl(QualType Ty);
+ /// Return the underlying ObjCInterfaceDecl if \arg Ty is an
+ /// ObjCInterface or a pointer to one.
+ ObjCInterfaceDecl *getObjCInterfaceDecl(QualType Ty);
- /// \brief Create new member and increase Offset by FType's size.
+ /// Create new member and increase Offset by FType's size.
llvm::DIType *CreateMemberType(llvm::DIFile *Unit, QualType FType,
StringRef Name, uint64_t *Offset);
- /// \brief Retrieve the DIDescriptor, if any, for the canonical form of this
+ /// Retrieve the DIDescriptor, if any, for the canonical form of this
/// declaration.
llvm::DINode *getDeclarationOrDefinition(const Decl *D);
- /// \brief Return debug info descriptor to describe method
+ /// \return debug info descriptor to describe method
/// declaration for the given method definition.
llvm::DISubprogram *getFunctionDeclaration(const Decl *D);
- /// Return debug info descriptor to describe in-class static data member
- /// declaration for the given out-of-class definition.
+ /// \return debug info descriptor to describe in-class static data
+ /// member declaration for the given out-of-class definition. If D
+ /// is an out-of-class definition of a static data member of a
+ /// class, find its corresponding in-class declaration.
llvm::DIDerivedType *
getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D);
- /// \brief Create a subprogram describing the forward
- /// decalration represented in the given FunctionDecl.
+ /// Create a subprogram describing the forward declaration
+ /// represented in the given FunctionDecl.
llvm::DISubprogram *getFunctionForwardDeclaration(const FunctionDecl *FD);
- /// \brief Create a global variable describing the forward decalration
+ /// Create a global variable describing the forward decalration
/// represented in the given VarDecl.
llvm::DIGlobalVariable *
getGlobalVariableForwardDeclaration(const VarDecl *VD);
- /// Return a global variable that represents one of the collection of
- /// global variables created for an anonmyous union.
+ /// \brief Return a global variable that represents one of the
+ /// collection of global variables created for an anonmyous union.
+ ///
+ /// Recursively collect all of the member fields of a global
+ /// anonymous decl and create static variables for them. The first
+ /// time this is called it needs to be on a union and then from
+ /// there we can have additional unnamed fields.
llvm::DIGlobalVariable *
CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile *Unit,
unsigned LineNo, StringRef LinkageName,
llvm::GlobalVariable *Var, llvm::DIScope *DContext);
- /// \brief Get function name for the given FunctionDecl. If the
- /// name is constructed on demand (e.g. C++ destructor) then the name
- /// is stored on the side.
+ /// Get function name for the given FunctionDecl. If the name is
+ /// constructed on demand (e.g., C++ destructor) then the name is
+ /// stored on the side.
StringRef getFunctionName(const FunctionDecl *FD);
- /// \brief Returns the unmangled name of an Objective-C method.
+ /// Returns the unmangled name of an Objective-C method.
/// This is the display name for the debugging info.
StringRef getObjCMethodName(const ObjCMethodDecl *FD);
- /// \brief Return selector name. This is used for debugging
+ /// Return selector name. This is used for debugging
/// info.
StringRef getSelectorName(Selector S);
- /// \brief Get class name including template argument list.
+ /// Get class name including template argument list.
StringRef getClassName(const RecordDecl *RD);
- /// \brief Get vtable name for the given Class.
+ /// Get the vtable name for the given class.
StringRef getVTableName(const CXXRecordDecl *Decl);
- /// \brief Get line number for the location. If location is invalid
+ /// Get line number for the location. If location is invalid
/// then use current location.
unsigned getLineNumber(SourceLocation Loc);
- /// \brief Get column number for the location. If location is
+ /// Get column number for the location. If location is
/// invalid then use current location.
/// \param Force Assume DebugColumnInfo option is true.
- unsigned getColumnNumber(SourceLocation Loc, bool Force=false);
+ unsigned getColumnNumber(SourceLocation Loc, bool Force = false);
- /// \brief Collect various properties of a FunctionDecl.
+ /// Collect various properties of a FunctionDecl.
/// \param GD A GlobalDecl whose getDecl() must return a FunctionDecl.
void collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
StringRef &Name, StringRef &LinkageName,
@@ -434,12 +474,12 @@ private:
llvm::DINodeArray &TParamsArray,
unsigned &Flags);
- /// \brief Collect various properties of a VarDecl.
+ /// 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);
- /// \brief Allocate a copy of \p A using the DebugInfoNames allocator
+ /// Allocate a copy of \p A using the DebugInfoNames allocator
/// and return a reference to it. If multiple arguments are given the strings
/// are concatenated.
StringRef internString(StringRef A, StringRef B = StringRef()) {
@@ -450,7 +490,7 @@ private:
}
};
-/// \brief A scoped helper to set the current debug location to the specified
+/// A scoped helper to set the current debug location to the specified
/// location or preferred location of the specified Expr.
class ApplyDebugLocation {
private:
@@ -460,55 +500,56 @@ private:
llvm::DebugLoc OriginalLocation;
CodeGenFunction &CGF;
-public:
- /// \brief Set the location to the (valid) TemporaryLocation.
+public:
+ /// Set the location to the (valid) TemporaryLocation.
ApplyDebugLocation(CodeGenFunction &CGF, SourceLocation TemporaryLocation);
ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E);
ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc);
~ApplyDebugLocation();
- /// \brief Apply TemporaryLocation if it is valid. Otherwise switch to an
- /// artificial debug location that has a valid scope, but no line information.
+ /// \brief Apply TemporaryLocation if it is valid. Otherwise switch
+ /// to an artificial debug location that has a valid scope, but no
+ /// line information.
///
- /// Artificial locations are useful when emitting compiler-generated helper
- /// functions that have no source location associated with them. The DWARF
- /// specification allows the compiler to use the special line number 0 to
- /// indicate code that can not be attributed to any source location. Note that
- /// passing an empty SourceLocation to CGDebugInfo::setLocation() will result
- /// in the last valid location being reused.
+ /// Artificial locations are useful when emitting compiler-generated
+ /// helper functions that have no source location associated with
+ /// them. The DWARF specification allows the compiler to use the
+ /// special line number 0 to indicate code that can not be
+ /// attributed to any source location. Note that passing an empty
+ /// SourceLocation to CGDebugInfo::setLocation() will result in the
+ /// last valid location being reused.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF) {
return ApplyDebugLocation(CGF, false, SourceLocation());
}
- /// \brief Apply TemporaryLocation if it is valid. Otherwise switch to an
- /// artificial debug location that has a valid scope, but no line information.
- static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF,
- SourceLocation TemporaryLocation) {
+ /// \brief Apply TemporaryLocation if it is valid. Otherwise switch
+ /// to an artificial debug location that has a valid scope, but no
+ /// line information.
+ static ApplyDebugLocation
+ CreateDefaultArtificial(CodeGenFunction &CGF,
+ SourceLocation TemporaryLocation) {
return ApplyDebugLocation(CGF, false, TemporaryLocation);
}
- /// \brief Set the IRBuilder to not attach debug locations. Note that passing
- /// an empty SourceLocation to CGDebugInfo::setLocation() will result in the
- /// last valid location being reused. Note that all instructions that do not
- /// have a location at the beginning of a function are counted towards to
- /// funciton prologue.
+ /// Set the IRBuilder to not attach debug locations. Note that
+ /// passing an empty SourceLocation to \a CGDebugInfo::setLocation()
+ /// will result in the last valid location being reused. Note that
+ /// all instructions that do not have a location at the beginning of
+ /// a function are counted towards to funciton prologue.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF) {
return ApplyDebugLocation(CGF, true, SourceLocation());
}
/// \brief Apply TemporaryLocation if it is valid. Otherwise set the IRBuilder
/// to not attach debug locations.
- static ApplyDebugLocation CreateDefaultEmpty(CodeGenFunction &CGF,
- SourceLocation TemporaryLocation) {
+ static ApplyDebugLocation
+ CreateDefaultEmpty(CodeGenFunction &CGF, SourceLocation TemporaryLocation) {
return ApplyDebugLocation(CGF, true, TemporaryLocation);
}
-
};
-
} // namespace CodeGen
} // namespace clang
-
#endif
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 839c2e474ca3..96aa8c68e004 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -79,6 +79,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::Captured:
case Decl::ClassScopeFunctionSpecialization:
case Decl::UsingShadow:
+ case Decl::ObjCTypeParam:
llvm_unreachable("Declaration should not be in declstmts!");
case Decl::Function: // void X();
case Decl::Record: // struct/union/class X;
@@ -987,7 +988,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
llvm::Value *Stack = CreateTempAlloca(Int8PtrTy, "saved_stack");
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave);
- llvm::Value *V = Builder.CreateCall(F, {});
+ llvm::Value *V = Builder.CreateCall(F);
Builder.CreateStore(V, Stack);
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 4c8501724bd8..7b8368ee2b32 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/TargetBuiltins.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -1279,14 +1280,6 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {
}
void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
- // FIXME: Implement SEH on other architectures.
- const llvm::Triple &T = CGM.getTarget().getTriple();
- if (T.getArch() != llvm::Triple::x86_64 ||
- !T.isKnownWindowsMSVCEnvironment()) {
- ErrorUnsupported(&S, "__try statement");
- return;
- }
-
EnterSEHTryStmt(S);
{
JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
@@ -1311,24 +1304,27 @@ struct PerformSEHFinally : EHScopeStack::Cleanup {
void Emit(CodeGenFunction &CGF, Flags F) override {
ASTContext &Context = CGF.getContext();
- QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy};
- FunctionProtoType::ExtProtoInfo EPI;
- const auto *FTP = cast<FunctionType>(
- Context.getFunctionType(Context.VoidTy, ArgTys, EPI));
+ CodeGenModule &CGM = CGF.CGM;
CallArgList Args;
+
+ // 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 *IsForEH =
llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
Args.add(RValue::get(IsForEH), ArgTys[0]);
-
- CodeGenModule &CGM = CGF.CGM;
- llvm::Value *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0);
- llvm::Value *FrameAddr = CGM.getIntrinsic(llvm::Intrinsic::frameaddress);
- llvm::Value *FP = CGF.Builder.CreateCall(FrameAddr, Zero);
Args.add(RValue::get(FP), ArgTys[1]);
+ // Arrange a two-arg function info and type.
+ FunctionProtoType::ExtProtoInfo EPI;
+ const auto *FPT = cast<FunctionProtoType>(
+ Context.getFunctionType(Context.VoidTy, ArgTys, EPI));
const CGFunctionInfo &FnInfo =
- CGM.getTypes().arrangeFreeFunctionCall(Args, FTP, /*chainCall=*/false);
+ CGM.getTypes().arrangeFreeFunctionCall(Args, FPT,
+ /*chainCall=*/false);
+
CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
}
};
@@ -1340,9 +1336,15 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
CodeGenFunction &ParentCGF;
const VarDecl *ParentThis;
SmallVector<const VarDecl *, 4> Captures;
+ llvm::Value *SEHCodeSlot = nullptr;
CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis)
: ParentCGF(ParentCGF), ParentThis(ParentThis) {}
+ // Return true if we need to do any capturing work.
+ bool foundCaptures() {
+ return !Captures.empty() || SEHCodeSlot;
+ }
+
void Visit(const Stmt *S) {
// See if this is a capture, then recurse.
ConstStmtVisitor<CaptureFinder>::Visit(S);
@@ -1366,27 +1368,106 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
void VisitCXXThisExpr(const CXXThisExpr *E) {
Captures.push_back(ParentThis);
}
+
+ void VisitCallExpr(const CallExpr *E) {
+ // We only need to add parent frame allocations for these builtins in x86.
+ if (ParentCGF.getTarget().getTriple().getArch() != llvm::Triple::x86)
+ return;
+
+ unsigned ID = E->getBuiltinCallee();
+ switch (ID) {
+ case Builtin::BI__exception_code:
+ case Builtin::BI_exception_code:
+ // This is the simple case where we are the outermost finally. All we
+ // have to do here is make sure we escape this and recover it in the
+ // outlined handler.
+ if (!SEHCodeSlot)
+ SEHCodeSlot = ParentCGF.SEHCodeSlotStack.back();
+ break;
+ }
+ }
};
}
+llvm::Value *CodeGenFunction::recoverAddrOfEscapedLocal(
+ CodeGenFunction &ParentCGF, llvm::Value *ParentVar, llvm::Value *ParentFP) {
+ llvm::CallInst *RecoverCall = nullptr;
+ CGBuilderTy Builder(AllocaInsertPt);
+ if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
+ // Mark the variable escaped if nobody else referenced it and compute the
+ // localescape index.
+ auto InsertPair = ParentCGF.EscapedLocals.insert(
+ std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size()));
+ int FrameEscapeIdx = InsertPair.first->second;
+ // call i8* @llvm.localrecover(i8* bitcast(@parentFn), i8* %fp, i32 N)
+ llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
+ &CGM.getModule(), llvm::Intrinsic::localrecover);
+ llvm::Constant *ParentI8Fn =
+ llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
+ RecoverCall = Builder.CreateCall(
+ FrameRecoverFn, {ParentI8Fn, ParentFP,
+ llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
+
+ } else {
+ // If the parent didn't have an alloca, we're doing some nested outlining.
+ // Just clone the existing localrecover call, but tweak the FP argument to
+ // use our FP value. All other arguments are constants.
+ auto *ParentRecover =
+ cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts());
+ assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover &&
+ "expected alloca or localrecover in parent LocalDeclMap");
+ RecoverCall = cast<llvm::CallInst>(ParentRecover->clone());
+ RecoverCall->setArgOperand(1, ParentFP);
+ RecoverCall->insertBefore(AllocaInsertPt);
+ }
+
+ // Bitcast the variable, rename it, and insert it in the local decl map.
+ llvm::Value *ChildVar =
+ Builder.CreateBitCast(RecoverCall, ParentVar->getType());
+ ChildVar->setName(ParentVar->getName());
+ return ChildVar;
+}
+
void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
const Stmt *OutlinedStmt,
- llvm::Value *ParentFP) {
+ bool IsFilter) {
// Find all captures in the Stmt.
CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl);
Finder.Visit(OutlinedStmt);
- // Typically there are no captures and we can exit early.
- if (Finder.Captures.empty())
+ // We can exit early on x86_64 when there are no captures. We just have to
+ // save the exception code in filters so that __exception_code() works.
+ if (!Finder.foundCaptures() &&
+ CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
+ if (IsFilter)
+ EmitSEHExceptionCodeSave(ParentCGF, nullptr, nullptr);
return;
+ }
- // Prepare the first two arguments to llvm.framerecover.
- llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
- &CGM.getModule(), llvm::Intrinsic::framerecover);
- llvm::Constant *ParentI8Fn =
- llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
+ llvm::Value *EntryEBP = nullptr;
+ llvm::Value *ParentFP;
+ if (IsFilter && CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) {
+ // 32-bit SEH filters need to be careful about FP recovery. The end of the
+ // EH registration is passed in as the EBP physical register. We can
+ // recover that with llvm.frameaddress(1), and adjust that to recover the
+ // parent's true frame pointer.
+ CGBuilderTy Builder(AllocaInsertPt);
+ EntryEBP = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::frameaddress), {Builder.getInt32(1)});
+ llvm::Function *RecoverFPIntrin =
+ CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp);
+ llvm::Constant *ParentI8Fn =
+ llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
+ ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryEBP});
+ } else {
+ // Otherwise, for x64 and 32-bit finally functions, the parent FP is the
+ // second parameter.
+ auto AI = CurFn->arg_begin();
+ ++AI;
+ ParentFP = AI;
+ }
- // Create llvm.framerecover calls for all captures.
+ // Create llvm.localrecover calls for all captures.
for (const VarDecl *VD : Finder.Captures) {
if (isa<ImplicitParamDecl>(VD)) {
CGM.ErrorUnsupported(VD, "'this' captured by SEH");
@@ -1407,49 +1488,63 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
continue;
llvm::Value *ParentVar = I->second;
- llvm::CallInst *RecoverCall = nullptr;
- CGBuilderTy Builder(AllocaInsertPt);
- if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
- // Mark the variable escaped if nobody else referenced it and compute the
- // frameescape index.
- auto InsertPair =
- ParentCGF.EscapedLocals.insert(std::make_pair(ParentAlloca, -1));
- if (InsertPair.second)
- InsertPair.first->second = ParentCGF.EscapedLocals.size() - 1;
- int FrameEscapeIdx = InsertPair.first->second;
- // call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 N)
- RecoverCall = Builder.CreateCall(
- FrameRecoverFn, {ParentI8Fn, ParentFP,
- llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
-
- } else {
- // If the parent didn't have an alloca, we're doing some nested outlining.
- // Just clone the existing framerecover call, but tweak the FP argument to
- // use our FP value. All other arguments are constants.
- auto *ParentRecover =
- cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts());
- assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::framerecover &&
- "expected alloca or framerecover in parent LocalDeclMap");
- RecoverCall = cast<llvm::CallInst>(ParentRecover->clone());
- RecoverCall->setArgOperand(1, ParentFP);
- RecoverCall->insertBefore(AllocaInsertPt);
- }
+ LocalDeclMap[VD] =
+ recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP);
+ }
- // Bitcast the variable, rename it, and insert it in the local decl map.
- llvm::Value *ChildVar =
- Builder.CreateBitCast(RecoverCall, ParentVar->getType());
- ChildVar->setName(ParentVar->getName());
- LocalDeclMap[VD] = ChildVar;
+ if (Finder.SEHCodeSlot) {
+ SEHCodeSlotStack.push_back(
+ recoverAddrOfEscapedLocal(ParentCGF, Finder.SEHCodeSlot, ParentFP));
}
+
+ if (IsFilter)
+ EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryEBP);
}
/// Arrange a function prototype that can be called by Windows exception
/// handling personalities. On Win64, the prototype looks like:
/// RetTy func(void *EHPtrs, void *ParentFP);
void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
- StringRef Name, QualType RetTy,
- FunctionArgList &Args,
+ bool IsFilter,
const Stmt *OutlinedStmt) {
+ SourceLocation StartLoc = OutlinedStmt->getLocStart();
+
+ // Get the mangled function name.
+ SmallString<128> Name;
+ {
+ llvm::raw_svector_ostream OS(Name);
+ const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
+ const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
+ assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
+ MangleContext &Mangler = CGM.getCXXABI().getMangleContext();
+ if (IsFilter)
+ Mangler.mangleSEHFilterExpression(Parent, OS);
+ else
+ Mangler.mangleSEHFinallyBlock(Parent, OS);
+ }
+
+ FunctionArgList Args;
+ if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 || !IsFilter) {
+ // All SEH finally functions take two parameters. Win64 filters take two
+ // parameters. Win32 filters take no parameters.
+ if (IsFilter) {
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("exception_pointers"),
+ getContext().VoidPtrTy));
+ } else {
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("abnormal_termination"),
+ getContext().UnsignedCharTy));
+ }
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
+ }
+
+ QualType RetTy = IsFilter ? getContext().LongTy : getContext().VoidTy;
+
llvm::Function *ParentFn = ParentCGF.CurFn;
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false);
@@ -1474,10 +1569,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart());
CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn);
-
- auto AI = Fn->arg_begin();
- ++AI;
- EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI);
+ EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter);
}
/// Create a stub filter function that will ultimately hold the code of the
@@ -1487,37 +1579,7 @@ llvm::Function *
CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
const SEHExceptStmt &Except) {
const Expr *FilterExpr = Except.getFilterExpr();
- SourceLocation StartLoc = FilterExpr->getLocStart();
-
- SEHPointersDecl = ImplicitParamDecl::Create(
- getContext(), nullptr, StartLoc,
- &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy);
- FunctionArgList Args;
- Args.push_back(SEHPointersDecl);
- Args.push_back(ImplicitParamDecl::Create(
- getContext(), nullptr, StartLoc,
- &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
-
- // Get the mangled function name.
- SmallString<128> Name;
- {
- llvm::raw_svector_ostream OS(Name);
- const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
- const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
- assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
- CGM.getCXXABI().getMangleContext().mangleSEHFilterExpression(Parent, OS);
- }
-
- startOutlinedSEHHelper(ParentCGF, Name, getContext().LongTy, Args,
- FilterExpr);
-
- // Mark finally block calls as nounwind and noinline to make LLVM's job a
- // little easier.
- // FIXME: Remove these restrictions in the future.
- CurFn->addFnAttr(llvm::Attribute::NoUnwind);
- CurFn->addFnAttr(llvm::Attribute::NoInline);
-
- EmitSEHExceptionCodeSave();
+ startOutlinedSEHHelper(ParentCGF, true, FilterExpr);
// Emit the original filter expression, convert to i32, and return.
llvm::Value *R = EmitScalarExpr(FilterExpr);
@@ -1534,29 +1596,13 @@ llvm::Function *
CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
const SEHFinallyStmt &Finally) {
const Stmt *FinallyBlock = Finally.getBlock();
- SourceLocation StartLoc = FinallyBlock->getLocStart();
+ startOutlinedSEHHelper(ParentCGF, false, FinallyBlock);
- FunctionArgList Args;
- Args.push_back(ImplicitParamDecl::Create(
- getContext(), nullptr, StartLoc,
- &getContext().Idents.get("abnormal_termination"),
- getContext().UnsignedCharTy));
- Args.push_back(ImplicitParamDecl::Create(
- getContext(), nullptr, StartLoc,
- &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
-
- // Get the mangled function name.
- SmallString<128> Name;
- {
- llvm::raw_svector_ostream OS(Name);
- const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
- const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
- assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
- CGM.getCXXABI().getMangleContext().mangleSEHFinallyBlock(Parent, OS);
- }
-
- startOutlinedSEHHelper(ParentCGF, Name, getContext().VoidTy, Args,
- FinallyBlock);
+ // Mark finally block calls as nounwind and noinline to make LLVM's job a
+ // little easier.
+ // FIXME: Remove these restrictions in the future.
+ CurFn->addFnAttr(llvm::Attribute::NoUnwind);
+ CurFn->addFnAttr(llvm::Attribute::NoInline);
// Emit the original filter expression, convert to i32, and return.
EmitStmt(FinallyBlock);
@@ -1566,44 +1612,58 @@ CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
return CurFn;
}
-void CodeGenFunction::EmitSEHExceptionCodeSave() {
+void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
+ llvm::Value *ParentFP,
+ llvm::Value *EntryEBP) {
+ // Get the pointer to the EXCEPTION_POINTERS struct. This is returned by the
+ // __exception_info intrinsic.
+ if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
+ // On Win64, the info is passed as the first parameter to the filter.
+ auto AI = CurFn->arg_begin();
+ SEHInfo = AI;
+ SEHCodeSlotStack.push_back(
+ CreateMemTemp(getContext().IntTy, "__exception_code"));
+ } else {
+ // On Win32, the EBP on entry to the filter points to the end of an
+ // exception registration object. It contains 6 32-bit fields, and the info
+ // pointer is stored in the second field. So, GEP 20 bytes backwards and
+ // load the pointer.
+ SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryEBP, -20);
+ SEHInfo = Builder.CreateBitCast(SEHInfo, Int8PtrTy->getPointerTo());
+ SEHInfo = Builder.CreateLoad(Int8PtrTy, SEHInfo);
+ SEHCodeSlotStack.push_back(recoverAddrOfEscapedLocal(
+ ParentCGF, ParentCGF.SEHCodeSlotStack.back(), ParentFP));
+ }
+
// Save the exception code in the exception slot to unify exception access in
// the filter function and the landing pad.
// struct EXCEPTION_POINTERS {
// EXCEPTION_RECORD *ExceptionRecord;
// CONTEXT *ContextRecord;
// };
- // void *exn.slot =
- // (void *)(uintptr_t)exception_pointers->ExceptionRecord->ExceptionCode;
- llvm::Value *Ptrs = Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl));
+ // int exceptioncode = exception_pointers->ExceptionRecord->ExceptionCode;
llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo();
llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr);
- Ptrs = Builder.CreateBitCast(Ptrs, PtrsTy->getPointerTo());
+ llvm::Value *Ptrs = Builder.CreateBitCast(SEHInfo, PtrsTy->getPointerTo());
llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0);
Rec = Builder.CreateLoad(Rec);
llvm::Value *Code = Builder.CreateLoad(Rec);
- Code = Builder.CreateZExt(Code, CGM.IntPtrTy);
- // FIXME: Change landing pads to produce {i32, i32} and make the exception
- // slot an i32.
- Code = Builder.CreateIntToPtr(Code, CGM.VoidPtrTy);
- Builder.CreateStore(Code, getExceptionSlot());
+ assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
+ Builder.CreateStore(Code, SEHCodeSlotStack.back());
}
llvm::Value *CodeGenFunction::EmitSEHExceptionInfo() {
// Sema should diagnose calling this builtin outside of a filter context, but
// don't crash if we screw up.
- if (!SEHPointersDecl)
+ if (!SEHInfo)
return llvm::UndefValue::get(Int8PtrTy);
- return Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl));
+ assert(SEHInfo->getType() == Int8PtrTy);
+ return SEHInfo;
}
llvm::Value *CodeGenFunction::EmitSEHExceptionCode() {
- // If we're in a landing pad or filter function, the exception slot contains
- // the code.
- assert(ExceptionSlot);
- llvm::Value *Code =
- Builder.CreatePtrToInt(getExceptionFromSlot(), CGM.IntPtrTy);
- return Builder.CreateTrunc(Code, CGM.Int32Ty);
+ assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
+ return Builder.CreateLoad(Int32Ty, SEHCodeSlotStack.back());
}
llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
@@ -1616,9 +1676,11 @@ llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
- // Push a cleanup for __finally blocks.
+ // Outline the finally block.
llvm::Function *FinallyFunc =
HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
+
+ // Push a cleanup for __finally blocks.
EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc);
return;
}
@@ -1627,12 +1689,16 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
const SEHExceptStmt *Except = S.getExceptHandler();
assert(Except);
EHCatchScope *CatchScope = EHStack.pushCatch(1);
+ SEHCodeSlotStack.push_back(
+ CreateMemTemp(getContext().IntTy, "__exception_code"));
- // If the filter is known to evaluate to 1, then we can use the clause "catch
- // i8* null".
+ // If the filter is known to evaluate to 1, then we can use the clause
+ // "catch i8* null". We can't do this on x86 because the filter has to save
+ // the exception code.
llvm::Constant *C =
CGM.EmitConstantExpr(Except->getFilterExpr(), getContext().IntTy, this);
- if (C && C->isOneValue()) {
+ if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 && C &&
+ C->isOneValue()) {
CatchScope->setCatchAllHandler(0, createBasicBlock("__except"));
return;
}
@@ -1664,6 +1730,7 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
if (!CatchScope.hasEHBranches()) {
CatchScope.clearHandlerBlocks();
EHStack.popCatch();
+ SEHCodeSlotStack.pop_back();
return;
}
@@ -1683,9 +1750,20 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
EmitBlockAfterUses(ExceptBB);
+ // On Win64, the exception pointer is the exception code. Copy it to the slot.
+ if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
+ llvm::Value *Code =
+ Builder.CreatePtrToInt(getExceptionFromSlot(), IntPtrTy);
+ Code = Builder.CreateTrunc(Code, Int32Ty);
+ Builder.CreateStore(Code, SEHCodeSlotStack.back());
+ }
+
// Emit the __except body.
EmitStmt(Except->getBlock());
+ // End the lifetime of the exception code.
+ SEHCodeSlotStack.pop_back();
+
if (HaveInsertPoint())
Builder.CreateBr(ContBB);
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 175763c4e815..9c3dfe52716b 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1356,14 +1356,15 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) {
const CGBitFieldInfo &Info = LV.getBitFieldInfo();
+ CharUnits Align = LV.getAlignment().alignmentAtOffset(Info.StorageOffset);
// Get the output type.
llvm::Type *ResLTy = ConvertType(LV.getType());
llvm::Value *Ptr = LV.getBitFieldAddr();
- llvm::Value *Val = Builder.CreateLoad(Ptr, LV.isVolatileQualified(),
- "bf.load");
- cast<llvm::LoadInst>(Val)->setAlignment(Info.StorageAlignment);
+ llvm::Value *Val = Builder.CreateAlignedLoad(Ptr, Align.getQuantity(),
+ LV.isVolatileQualified(),
+ "bf.load");
if (Info.IsSigned) {
assert(static_cast<unsigned>(Info.Offset + Info.Size) <= Info.StorageSize);
@@ -1559,6 +1560,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
llvm::Value **Result) {
const CGBitFieldInfo &Info = Dst.getBitFieldInfo();
+ CharUnits Align = Dst.getAlignment().alignmentAtOffset(Info.StorageOffset);
llvm::Type *ResLTy = ConvertTypeForMem(Dst.getType());
llvm::Value *Ptr = Dst.getBitFieldAddr();
@@ -1575,9 +1577,9 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
// and mask together with source before storing.
if (Info.StorageSize != Info.Size) {
assert(Info.StorageSize > Info.Size && "Invalid bitfield size.");
- llvm::Value *Val = Builder.CreateLoad(Ptr, Dst.isVolatileQualified(),
- "bf.load");
- cast<llvm::LoadInst>(Val)->setAlignment(Info.StorageAlignment);
+ llvm::Value *Val = Builder.CreateAlignedLoad(Ptr, Align.getQuantity(),
+ Dst.isVolatileQualified(),
+ "bf.load");
// Mask the source value as needed.
if (!hasBooleanRepresentation(Dst.getType()))
@@ -1603,9 +1605,8 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
}
// Write the new value back out.
- llvm::StoreInst *Store = Builder.CreateStore(SrcVal, Ptr,
- Dst.isVolatileQualified());
- Store->setAlignment(Info.StorageAlignment);
+ Builder.CreateAlignedStore(SrcVal, Ptr, Align.getQuantity(),
+ Dst.isVolatileQualified());
// Return the new value of the bit-field, if requested.
if (Result) {
@@ -2415,8 +2416,7 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
}
llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
- llvm::CallInst *TrapCall =
- Builder.CreateCall(CGM.getIntrinsic(IntrID), {});
+ llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(IntrID));
if (!CGM.getCodeGenOpts().TrapFuncName.empty())
TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex,
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 747326e4c5bc..eb76ad1ce1f7 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -31,10 +31,9 @@ using namespace CodeGen;
typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult;
static TryEmitResult
tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e);
-static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
- QualType ET,
- const ObjCMethodDecl *Method,
- RValue Result);
+static RValue AdjustObjCObjectType(CodeGenFunction &CGF,
+ QualType ET,
+ RValue Result);
/// Given the address of a variable of pointer type, find the correct
/// null to store into it.
@@ -248,23 +247,22 @@ llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) {
return CGM.getObjCRuntime().GenerateProtocolRef(*this, E->getProtocol());
}
-/// \brief Adjust the type of the result of an Objective-C message send
-/// expression when the method has a related result type.
-static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
- QualType ExpT,
- const ObjCMethodDecl *Method,
- RValue Result) {
- if (!Method)
+/// \brief Adjust the type of an Objective-C object that doesn't match up due
+/// to type erasure at various points, e.g., related result types or the use
+/// of parameterized classes.
+static RValue AdjustObjCObjectType(CodeGenFunction &CGF, QualType ExpT,
+ RValue Result) {
+ if (!ExpT->isObjCRetainableType())
return Result;
- if (!Method->hasRelatedResultType() ||
- CGF.getContext().hasSameType(ExpT, Method->getReturnType()) ||
- !Result.isScalar())
+ // If the converted types are the same, we're done.
+ llvm::Type *ExpLLVMTy = CGF.ConvertType(ExpT);
+ if (ExpLLVMTy == Result.getScalarVal()->getType())
return Result;
-
- // We have applied a related result type. Cast the rvalue appropriately.
+
+ // We have applied a substitution. Cast the rvalue appropriately.
return RValue::get(CGF.Builder.CreateBitCast(Result.getScalarVal(),
- CGF.ConvertType(ExpT)));
+ ExpLLVMTy));
}
/// Decide whether to extend the lifetime of the receiver of a
@@ -449,7 +447,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
Builder.CreateStore(newSelf, selfAddr);
}
- return AdjustRelatedResultType(*this, E->getType(), method, result);
+ return AdjustObjCObjectType(*this, E->getType(), result);
}
namespace {
@@ -2011,7 +2009,7 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
// Call the marker asm if we made one, which we do only at -O0.
if (marker)
- Builder.CreateCall(marker, {});
+ Builder.CreateCall(marker);
return emitARCValueOperation(*this, value,
CGM.getARCEntrypoints().objc_retainAutoreleasedReturnValue,
diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp
index 5290a87cebf2..2ac6bb2e8a93 100644
--- a/lib/CodeGen/CGObjCRuntime.cpp
+++ b/lib/CodeGen/CGObjCRuntime.cpp
@@ -134,7 +134,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo(
CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize,
CGF.CGM.getContext().toBits(StorageSize),
- Alignment.getQuantity()));
+ CharUnits::fromQuantity(0)));
V = CGF.Builder.CreateBitCast(V,
llvm::Type::getIntNPtrTy(CGF.getLLVMContext(),
@@ -160,7 +160,7 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) override {
if (!MightThrow) {
- CGF.Builder.CreateCall(Fn, {})->setDoesNotThrow();
+ CGF.Builder.CreateCall(Fn)->setDoesNotThrow();
return;
}
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index 534d148209ba..81488398bb86 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -537,7 +537,7 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
break;
}
case OMPRTL__kmpc_barrier: {
- // Build void __kmpc_cancel_barrier(ident_t *loc, kmp_int32 global_tid);
+ // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
@@ -829,6 +829,15 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
break;
}
+ case OMPRTL__kmpc_cancel: {
+ // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
+ // kmp_int32 cncl_kind)
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
+ break;
+ }
}
return RTLFn;
}
@@ -923,6 +932,8 @@ llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
llvm::Constant *
CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
+ assert(!CGM.getLangOpts().OpenMPUseTLS ||
+ !CGM.getContext().getTargetInfo().isTLSSupported());
// Lookup the entry, lazily creating it if necessary.
return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Twine(CGM.getMangledName(VD)) + ".cache.");
@@ -932,6 +943,10 @@ llvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
const VarDecl *VD,
llvm::Value *VDAddr,
SourceLocation Loc) {
+ if (CGM.getLangOpts().OpenMPUseTLS &&
+ CGM.getContext().getTargetInfo().isTLSSupported())
+ return VDAddr;
+
auto VarTy = VDAddr->getType()->getPointerElementType();
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy),
@@ -961,6 +976,10 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit(
llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc,
bool PerformInit, CodeGenFunction *CGF) {
+ if (CGM.getLangOpts().OpenMPUseTLS &&
+ CGM.getContext().getTargetInfo().isTLSSupported())
+ return nullptr;
+
VD = VD->getDefinition(CGM.getContext());
if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
ThreadPrivateWithDefinition.insert(VD);
@@ -2723,18 +2742,18 @@ void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
}
-void CGOpenMPRuntime::emitCancellationPointCall(
- CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPDirectiveKind CancelRegion) {
- // Build call kmp_int32 OMPRTL__kmpc_cancellationpoint(ident_t *loc, kmp_int32
- // global_tid, kmp_int32 cncl_kind);
- enum {
- CancelNoreq = 0,
- CancelParallel = 1,
- CancelLoop = 2,
- CancelSections = 3,
- CancelTaskgroup = 4
- } CancelKind = CancelNoreq;
+namespace {
+enum RTCancelKind {
+ CancelNoreq = 0,
+ CancelParallel = 1,
+ CancelLoop = 2,
+ CancelSections = 3,
+ CancelTaskgroup = 4
+};
+}
+
+static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
+ RTCancelKind CancelKind = CancelNoreq;
if (CancelRegion == OMPD_parallel)
CancelKind = CancelParallel;
else if (CancelRegion == OMPD_for)
@@ -2745,14 +2764,22 @@ void CGOpenMPRuntime::emitCancellationPointCall(
assert(CancelRegion == OMPD_taskgroup);
CancelKind = CancelTaskgroup;
}
+ return CancelKind;
+}
+
+void CGOpenMPRuntime::emitCancellationPointCall(
+ CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind CancelRegion) {
+ // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
+ // global_tid, kmp_int32 cncl_kind);
if (auto *OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
auto CancelDest =
CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
if (CancelDest.isValid()) {
- llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc),
- getThreadID(CGF, Loc),
- CGF.Builder.getInt32(CancelKind)};
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
+ CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
// Ignore return result until untied tasks are supported.
auto *Result = CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
@@ -2774,3 +2801,36 @@ void CGOpenMPRuntime::emitCancellationPointCall(
}
}
+void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind CancelRegion) {
+ // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
+ // kmp_int32 cncl_kind);
+ if (auto *OMPRegionInfo =
+ dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
+ auto CancelDest =
+ CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
+ if (CancelDest.isValid()) {
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
+ CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
+ // Ignore return result until untied tasks are supported.
+ auto *Result =
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
+ // if (__kmpc_cancel()) {
+ // __kmpc_cancel_barrier();
+ // exit from construct;
+ // }
+ auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
+ auto *ContBB = CGF.createBasicBlock(".cancel.continue");
+ auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
+ CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
+ CGF.EmitBlock(ExitBB);
+ // __kmpc_cancel_barrier();
+ emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false);
+ // exit from construct;
+ CGF.EmitBranchThroughCleanup(CancelDest);
+ CGF.EmitBlock(ContBB, /*IsFinished=*/true);
+ }
+ }
+}
+
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index 76bb3ae35931..44bc8a139b15 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -151,6 +151,9 @@ private:
// Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
// global_tid, kmp_int32 cncl_kind);
OMPRTL__kmpc_cancellationpoint,
+ // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
+ // kmp_int32 cncl_kind);
+ OMPRTL__kmpc_cancel,
};
/// \brief Values for bit flags used in the ident_t to describe the fields.
@@ -698,6 +701,12 @@ public:
virtual void emitCancellationPointCall(CodeGenFunction &CGF,
SourceLocation Loc,
OpenMPDirectiveKind CancelRegion);
+
+ /// \brief Emit code for 'cancel' construct.
+ /// \param CancelRegion Region kind for which the cancel must be emitted.
+ ///
+ virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind CancelRegion);
};
} // namespace CodeGen
diff --git a/lib/CodeGen/CGRecordLayout.h b/lib/CodeGen/CGRecordLayout.h
index c15f9fde06f5..d4ad33e3345e 100644
--- a/lib/CodeGen/CGRecordLayout.h
+++ b/lib/CodeGen/CGRecordLayout.h
@@ -78,16 +78,16 @@ struct CGBitFieldInfo {
/// bitfield.
unsigned StorageSize;
- /// The alignment which should be used when accessing the bitfield.
- unsigned StorageAlignment;
+ /// The offset of the bitfield storage from the start of the struct.
+ CharUnits StorageOffset;
CGBitFieldInfo()
- : Offset(), Size(), IsSigned(), StorageSize(), StorageAlignment() {}
+ : Offset(), Size(), IsSigned(), StorageSize(), StorageOffset() {}
CGBitFieldInfo(unsigned Offset, unsigned Size, bool IsSigned,
- unsigned StorageSize, unsigned StorageAlignment)
+ unsigned StorageSize, CharUnits StorageOffset)
: Offset(Offset), Size(Size), IsSigned(IsSigned),
- StorageSize(StorageSize), StorageAlignment(StorageAlignment) {}
+ StorageSize(StorageSize), StorageOffset(StorageOffset) {}
void print(raw_ostream &OS) const;
void dump() const;
@@ -99,7 +99,7 @@ struct CGBitFieldInfo {
const FieldDecl *FD,
uint64_t Offset, uint64_t Size,
uint64_t StorageSize,
- uint64_t StorageAlignment);
+ CharUnits StorageOffset);
};
/// CGRecordLayout - This class handles struct and union layout info while
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index c89d5cc3892a..f91ecebd0926 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -228,11 +228,7 @@ void CGRecordLowering::setBitFieldInfo(
Info.Offset = (unsigned)(getFieldBitOffset(FD) - Context.toBits(StartOffset));
Info.Size = FD->getBitWidthValue(Context);
Info.StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType);
- // Here we calculate the actual storage alignment of the bits. E.g if we've
- // got an alignment >= 2 and the bitfield starts at offset 6 we've got an
- // alignment of 2.
- Info.StorageAlignment =
- Layout.getAlignment().alignmentAtOffset(StartOffset).getQuantity();
+ Info.StorageOffset = StartOffset;
if (Info.Size > Info.StorageSize)
Info.Size = Info.StorageSize;
// Reverse the bit offsets for big endian machines. Because we represent
@@ -651,7 +647,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
const FieldDecl *FD,
uint64_t Offset, uint64_t Size,
uint64_t StorageSize,
- uint64_t StorageAlignment) {
+ CharUnits StorageOffset) {
// This function is vestigial from CGRecordLayoutBuilder days but is still
// used in GCObjCRuntime.cpp. That usage has a "fixme" attached to it that
// when addressed will allow for the removal of this function.
@@ -683,7 +679,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
Offset = StorageSize - (Offset + Size);
}
- return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageAlignment);
+ return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageOffset);
}
CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D,
@@ -856,7 +852,7 @@ void CGBitFieldInfo::print(raw_ostream &OS) const {
<< " Size:" << Size
<< " IsSigned:" << IsSigned
<< " StorageSize:" << StorageSize
- << " StorageAlignment:" << StorageAlignment << ">";
+ << " StorageOffset:" << StorageOffset.getQuantity() << ">";
}
void CGBitFieldInfo::dump() const {
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index a12f29534bfe..7a0b8a35be01 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -1852,6 +1852,14 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
std::vector<llvm::Value*> InOutArgs;
std::vector<llvm::Type*> InOutArgTypes;
+ // An inline asm can be marked readonly if it meets the following conditions:
+ // - it doesn't have any sideeffects
+ // - it doesn't clobber memory
+ // - it doesn't return a value by-reference
+ // It can be marked readnone if it doesn't have any input memory constraints
+ // in addition to meeting the conditions listed above.
+ bool ReadOnly = true, ReadNone = true;
+
for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
@@ -1915,6 +1923,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Args.push_back(Dest.getAddress());
Constraints += "=*";
Constraints += OutputConstraint;
+ ReadOnly = ReadNone = false;
}
if (Info.isReadWrite()) {
@@ -1959,6 +1968,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+ if (Info.allowsMemory())
+ ReadNone = false;
+
if (!Constraints.empty())
Constraints += ',';
@@ -2023,7 +2035,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
StringRef Clobber = S.getClobber(i);
- if (Clobber != "memory" && Clobber != "cc")
+ if (Clobber == "memory")
+ ReadOnly = ReadNone = false;
+ else if (Clobber != "cc")
Clobber = getTarget().getNormalizedGCCRegisterName(Clobber);
if (!Constraints.empty())
@@ -2063,6 +2077,16 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoUnwind);
+ // Attach readnone and readonly attributes.
+ if (!HasSideEffect) {
+ if (ReadNone)
+ Result->addAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::ReadNone);
+ else if (ReadOnly)
+ Result->addAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::ReadOnly);
+ }
+
// Slap the source location of the inline asm into a !srcloc metadata on the
// call.
if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S)) {
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index b021c1275318..a1f093a8d866 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -2108,7 +2108,8 @@ void CodeGenFunction::EmitOMPCancellationPointDirective(
}
void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
- llvm_unreachable("CodeGen for 'omp cancel' is not supported yet.");
+ CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(),
+ S.getCancelRegion());
}
CodeGenFunction::JumpDest
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 969629fb5845..e36051c2053b 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -364,7 +364,7 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
FinishFunction();
}
-void CodeGenFunction::GenerateThunk(llvm::Function *Fn,
+void CodeGenFunction::generateThunk(llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk) {
StartThunk(Fn, GD, FnInfo);
@@ -376,13 +376,6 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn,
// Make the call and return the result.
EmitCallAndReturnForThunk(Callee, &Thunk);
-
- // Set the right linkage.
- CGM.setFunctionLinkage(GD, Fn);
-
- // Set the right visibility.
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- setThunkVisibility(CGM, MD, Thunk, Fn);
}
void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
@@ -455,11 +448,17 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk);
} else {
// Normal thunk body generation.
- CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk);
+ CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, Thunk);
}
+ CGM.setFunctionLinkage(GD, ThunkFn);
CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD,
!Thunk.Return.isEmpty());
+
+ // Set the right visibility.
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ setThunkVisibility(CGM, MD, Thunk, ThunkFn);
+
if (CGM.supportsCOMDAT() && ThunkFn->isWeakForLinker())
ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));
}
@@ -841,6 +840,11 @@ void CodeGenModule::EmitDeferredVTables() {
DeferredVTables.clear();
}
+bool CodeGenModule::IsCFIBlacklistedRecord(const CXXRecordDecl *RD) {
+ // FIXME: Make this user configurable.
+ return RD->isInStdNamespace();
+}
+
void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
const VTableLayout &VTLayout) {
if (!LangOpts.Sanitize.has(SanitizerKind::CFIVCall) &&
@@ -855,8 +859,7 @@ void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
std::vector<llvm::MDTuple *> BitsetEntries;
// Create a bit set entry for each address point.
for (auto &&AP : VTLayout.getAddressPoints()) {
- // FIXME: Add blacklisting scheme.
- if (AP.first.getBase()->isInStdNamespace())
+ if (IsCFIBlacklistedRecord(AP.first.getBase()))
continue;
BitsetEntries.push_back(CreateVTableBitSetEntry(
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 5a060b30808b..10bda76b6b69 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -10,6 +10,7 @@ set(LLVM_LINK_COMPONENTS
Linker
MC
ObjCARCOpts
+ Object
ProfileData
ScalarOpts
Support
@@ -71,6 +72,7 @@ add_clang_library(clangCodeGen
ItaniumCXXABI.cpp
MicrosoftCXXABI.cpp
ModuleBuilder.cpp
+ ObjectFilePCHContainerOperations.cpp
SanitizerMetadata.cpp
TargetInfo.cpp
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 1fca466e9244..ec3c75ccd257 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -45,12 +45,12 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr),
NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr),
ExceptionSlot(nullptr), EHSelectorSlot(nullptr),
- AbnormalTerminationSlot(nullptr), SEHPointersDecl(nullptr),
- DebugInfo(CGM.getModuleDebugInfo()), DisableDebugInfo(false),
- DidCallStackSave(false), IndirectBranch(nullptr), PGO(cgm),
- SwitchInsn(nullptr), SwitchWeights(nullptr), CaseRangeBlock(nullptr),
- UnreachableBlock(nullptr), NumReturnExprs(0), NumSimpleReturnExprs(0),
- CXXABIThisDecl(nullptr), CXXABIThisValue(nullptr), CXXThisValue(nullptr),
+ DebugInfo(CGM.getModuleDebugInfo()),
+ DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr),
+ PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr),
+ CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0),
+ NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr),
+ CXXABIThisValue(nullptr), CXXThisValue(nullptr),
CXXDefaultInitExprThis(nullptr), CXXStructorImplicitParamDecl(nullptr),
CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr),
CurLexicalScope(nullptr), TerminateLandingPad(nullptr),
@@ -284,7 +284,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
Builder.ClearInsertionPoint();
}
- // If some of our locals escaped, insert a call to llvm.frameescape in the
+ // If some of our locals escaped, insert a call to llvm.localescape in the
// entry block.
if (!EscapedLocals.empty()) {
// Invert the map from local to index into a simple vector. There should be
@@ -294,7 +294,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
for (auto &Pair : EscapedLocals)
EscapeArgs[Pair.second] = Pair.first;
llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration(
- &CGM.getModule(), llvm::Intrinsic::frameescape);
+ &CGM.getModule(), llvm::Intrinsic::localescape);
CGBuilderTy(AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index a74c474232c8..f2bc402f8b25 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -324,11 +324,13 @@ public:
/// write the current selector value into this alloca.
llvm::AllocaInst *EHSelectorSlot;
- llvm::AllocaInst *AbnormalTerminationSlot;
+ /// A stack of exception code slots. Entering an __except block pushes a slot
+ /// on the stack and leaving pops one. The __exception_code() intrinsic loads
+ /// a value from the top of the stack.
+ SmallVector<llvm::Value *, 1> SEHCodeSlotStack;
- /// The implicit parameter to SEH filter functions of type
- /// 'EXCEPTION_POINTERS*'.
- ImplicitParamDecl *SEHPointersDecl;
+ /// Value returned by __exception_info intrinsic.
+ llvm::Value *SEHInfo = nullptr;
/// Emits a landing pad for the current EH stack.
llvm::BasicBlock *EmitLandingPad();
@@ -886,7 +888,7 @@ private:
DeclMapTy LocalDeclMap;
/// Track escaped local variables with auto storage. Used during SEH
- /// outlining to produce a call to llvm.frameescape.
+ /// outlining to produce a call to llvm.localescape.
llvm::DenseMap<llvm::AllocaInst *, int> EscapedLocals;
/// LabelMap - This keeps track of the LLVM basic block for each C label.
@@ -1292,8 +1294,8 @@ public:
void EmitMustTailThunk(const CXXMethodDecl *MD, llvm::Value *AdjustedThisPtr,
llvm::Value *Callee);
- /// GenerateThunk - Generate a thunk for the given method.
- void GenerateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
+ /// Generate a thunk for the given method.
+ void generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk);
llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn,
@@ -2048,8 +2050,7 @@ public:
void EnterSEHTryStmt(const SEHTryStmt &S);
void ExitSEHTryStmt(const SEHTryStmt &S);
- void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StringRef Name,
- QualType RetTy, FunctionArgList &Args,
+ void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter,
const Stmt *OutlinedStmt);
llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
@@ -2058,16 +2059,27 @@ public:
llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
const SEHFinallyStmt &Finally);
- void EmitSEHExceptionCodeSave();
+ void EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
+ llvm::Value *ParentFP,
+ llvm::Value *EntryEBP);
llvm::Value *EmitSEHExceptionCode();
llvm::Value *EmitSEHExceptionInfo();
llvm::Value *EmitSEHAbnormalTermination();
/// Scan the outlined statement for captures from the parent function. For
/// each capture, mark the capture as escaped and emit a call to
- /// llvm.framerecover. Insert the framerecover result into the LocalDeclMap.
+ /// llvm.localrecover. Insert the localrecover result into the LocalDeclMap.
void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt,
- llvm::Value *ParentFP);
+ bool IsFilter);
+
+ /// Recovers the address of a local in a parent function. ParentVar is the
+ /// address of the variable used in the immediate parent function. It can
+ /// either be an alloca or a call to llvm.localrecover if there are nested
+ /// outlined functions. ParentFP is the frame pointer of the outermost parent
+ /// frame.
+ llvm::Value *recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
+ llvm::Value *ParentVar,
+ llvm::Value *ParentFP);
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> Attrs = None);
@@ -2931,6 +2943,26 @@ private:
SourceLocation Loc);
public:
+#ifndef NDEBUG
+ // Determine whether the given argument is an Objective-C method
+ // that may have type parameters in its signature.
+ static bool isObjCMethodWithTypeParams(const ObjCMethodDecl *method) {
+ const DeclContext *dc = method->getDeclContext();
+ if (const ObjCInterfaceDecl *classDecl= dyn_cast<ObjCInterfaceDecl>(dc)) {
+ return classDecl->getTypeParamListAsWritten();
+ }
+
+ if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) {
+ return catDecl->getTypeParamList();
+ }
+
+ return false;
+ }
+
+ template<typename T>
+ static bool isObjCMethodWithTypeParams(const T *) { return false; }
+#endif
+
/// EmitCallArgs - Emit call arguments for a function.
template <typename T>
void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo,
@@ -2944,18 +2976,25 @@ public:
assert((ParamsToSkip == 0 || CallArgTypeInfo) &&
"Can't skip parameters if type info is not provided");
if (CallArgTypeInfo) {
+#ifndef NDEBUG
+ bool isGenericMethod = isObjCMethodWithTypeParams(CallArgTypeInfo);
+#endif
+
// First, use the argument types that the type info knows about
for (auto I = CallArgTypeInfo->param_type_begin() + ParamsToSkip,
E = CallArgTypeInfo->param_type_end();
I != E; ++I, ++Arg) {
assert(Arg != ArgEnd && "Running over edge of argument list!");
- assert(
- ((*I)->isVariablyModifiedType() ||
- getContext()
- .getCanonicalType((*I).getNonReferenceType())
- .getTypePtr() ==
- getContext().getCanonicalType(Arg->getType()).getTypePtr()) &&
- "type mismatch in call argument!");
+ assert((isGenericMethod ||
+ ((*I)->isVariablyModifiedType() ||
+ (*I).getNonReferenceType()->isObjCRetainableType() ||
+ getContext()
+ .getCanonicalType((*I).getNonReferenceType())
+ .getTypePtr() ==
+ getContext()
+ .getCanonicalType(Arg->getType())
+ .getTypePtr())) &&
+ "type mismatch in call argument!");
ArgTypes.push_back(*I);
}
}
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index b905bd2b36bf..a179ad42eac1 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1262,6 +1262,11 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
// Implicit template instantiations may change linkage if they are later
// explicitly instantiated, so they should not be emitted eagerly.
return false;
+ // If OpenMP is enabled and threadprivates must be generated like TLS, delay
+ // codegen for global variables, because they may be marked as threadprivate.
+ if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS &&
+ getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global))
+ return false;
return true;
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 9a295feaffa4..dd167a29f5ac 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -1126,6 +1126,10 @@ public:
/// \param D Threadprivate declaration.
void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D);
+ /// Returns whether the given record is blacklisted from control flow
+ /// integrity checks.
+ bool IsCFIBlacklistedRecord(const CXXRecordDecl *RD);
+
/// Emit bit set entries for the given vtable using the given layout if
/// vptr CFI is enabled.
void EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index fa86e52ec804..70af69b76457 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2095,7 +2095,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
CGBuilderTy Builder(Entry);
if (InitIsInitFunc) {
if (Init)
- Builder.CreateCall(Init, {});
+ Builder.CreateCall(Init);
} else {
// Don't know whether we have an init function. Call it if it exists.
llvm::Value *Have = Builder.CreateIsNotNull(Init);
@@ -2104,7 +2104,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
Builder.CreateCondBr(Have, InitBB, ExitBB);
Builder.SetInsertPoint(InitBB);
- Builder.CreateCall(Init, {});
+ Builder.CreateCall(Init);
Builder.CreateBr(ExitBB);
Builder.SetInsertPoint(ExitBB);
@@ -2133,7 +2133,7 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD, Ty);
llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
- Val = CGF.Builder.CreateCall(Wrapper, {});
+ Val = CGF.Builder.CreateCall(Wrapper);
LValue LV;
if (VD->getType()->isReferenceType())
@@ -3620,7 +3620,7 @@ static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) {
catchCall->setCallingConv(CGM.getRuntimeCC());
// Call std::terminate().
- llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn(), {});
+ llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn());
termCall->setDoesNotThrow();
termCall->setDoesNotReturn();
termCall->setCallingConv(CGM.getRuntimeCC());
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index d149df63c9e4..3433990e1288 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1466,20 +1466,27 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
llvm::NamedMDNode *BitsetsMD =
CGM.getModule().getOrInsertNamedMetadata("llvm.bitsets");
- CharUnits PointerWidth = getContext().toCharUnitsFromBits(
- getContext().getTargetInfo().getPointerWidth(0));
- // FIXME: Add blacklisting scheme.
+ // The location of the first virtual function pointer in the virtual table,
+ // aka the "address point" on Itanium. This is at offset 0 if RTTI is
+ // disabled, or sizeof(void*) if RTTI is enabled.
+ CharUnits AddressPoint =
+ getContext().getLangOpts().RTTIData
+ ? getContext().toCharUnitsFromBits(
+ getContext().getTargetInfo().getPointerWidth(0))
+ : CharUnits::Zero();
if (Info->PathToBaseWithVPtr.empty()) {
- BitsetsMD->addOperand(
- CGM.CreateVTableBitSetEntry(VTable, PointerWidth, RD));
+ if (!CGM.IsCFIBlacklistedRecord(RD))
+ BitsetsMD->addOperand(
+ CGM.CreateVTableBitSetEntry(VTable, AddressPoint, RD));
return;
}
// Add a bitset entry for the least derived base belonging to this vftable.
- BitsetsMD->addOperand(CGM.CreateVTableBitSetEntry(
- VTable, PointerWidth, Info->PathToBaseWithVPtr.back()));
+ if (!CGM.IsCFIBlacklistedRecord(Info->PathToBaseWithVPtr.back()))
+ BitsetsMD->addOperand(CGM.CreateVTableBitSetEntry(
+ VTable, AddressPoint, Info->PathToBaseWithVPtr.back()));
// Add a bitset entry for each derived class that is laid out at the same
// offset as the least derived base.
@@ -1497,14 +1504,15 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
Offset = VBI->second.VBaseOffset;
if (!Offset.isZero())
return;
- BitsetsMD->addOperand(
- CGM.CreateVTableBitSetEntry(VTable, PointerWidth, DerivedRD));
+ if (!CGM.IsCFIBlacklistedRecord(DerivedRD))
+ BitsetsMD->addOperand(
+ CGM.CreateVTableBitSetEntry(VTable, AddressPoint, DerivedRD));
}
// Finally do the same for the most derived class.
- if (Info->FullOffsetInMDC.isZero())
+ if (Info->FullOffsetInMDC.isZero() && !CGM.IsCFIBlacklistedRecord(RD))
BitsetsMD->addOperand(
- CGM.CreateVTableBitSetEntry(VTable, PointerWidth, RD));
+ CGM.CreateVTableBitSetEntry(VTable, AddressPoint, RD));
}
void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -1707,7 +1715,7 @@ static const CXXRecordDecl *getClassAtVTableLocation(ASTContext &Ctx,
for (auto &&B : RD->bases()) {
const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
CharUnits BaseOffset = Layout.getBaseClassOffset(Base);
- if (BaseOffset <= Offset && BaseOffset > MaxBaseOffset) {
+ if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) {
MaxBase = Base;
MaxBaseOffset = BaseOffset;
}
@@ -1715,7 +1723,7 @@ static const CXXRecordDecl *getClassAtVTableLocation(ASTContext &Ctx,
for (auto &&B : RD->vbases()) {
const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
CharUnits BaseOffset = Layout.getVBaseClassOffset(Base);
- if (BaseOffset <= Offset && BaseOffset > MaxBaseOffset) {
+ if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) {
MaxBase = Base;
MaxBaseOffset = BaseOffset;
}
diff --git a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
new file mode 100644
index 000000000000..8f04e06988d8
--- /dev/null
+++ b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
@@ -0,0 +1,193 @@
+//===--- ObjectFilePCHContainerOperations.cpp -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
+#include "CGDebugInfo.h"
+#include "CodeGenModule.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/BackendUtil.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Serialization/ASTWriter.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/TargetRegistry.h"
+#include <memory>
+using namespace clang;
+
+#define DEBUG_TYPE "pchcontainer"
+
+namespace {
+class PCHContainerGenerator : public ASTConsumer {
+ DiagnosticsEngine &Diags;
+ const std::string MainFileName;
+ ASTContext *Ctx;
+ const HeaderSearchOptions &HeaderSearchOpts;
+ const PreprocessorOptions &PreprocessorOpts;
+ CodeGenOptions CodeGenOpts;
+ const TargetOptions TargetOpts;
+ const LangOptions LangOpts;
+ std::unique_ptr<llvm::LLVMContext> VMContext;
+ std::unique_ptr<llvm::Module> M;
+ std::unique_ptr<CodeGen::CodeGenModule> Builder;
+ raw_pwrite_stream *OS;
+ std::shared_ptr<PCHBuffer> Buffer;
+
+public:
+ PCHContainerGenerator(DiagnosticsEngine &diags,
+ const HeaderSearchOptions &HSO,
+ const PreprocessorOptions &PPO, const TargetOptions &TO,
+ const LangOptions &LO, const std::string &MainFileName,
+ const std::string &OutputFileName,
+ raw_pwrite_stream *OS,
+ std::shared_ptr<PCHBuffer> Buffer)
+ : Diags(diags), HeaderSearchOpts(HSO), PreprocessorOpts(PPO),
+ TargetOpts(TO), LangOpts(LO), OS(OS), Buffer(Buffer) {
+ // The debug info output isn't affected by CodeModel and
+ // ThreadModel, but the backend expects them to be nonempty.
+ CodeGenOpts.CodeModel = "default";
+ CodeGenOpts.ThreadModel = "single";
+ CodeGenOpts.setDebugInfo(CodeGenOptions::FullDebugInfo);
+ CodeGenOpts.SplitDwarfFile = OutputFileName;
+ }
+
+ virtual ~PCHContainerGenerator() {}
+
+ void Initialize(ASTContext &Context) override {
+ Ctx = &Context;
+ VMContext.reset(new llvm::LLVMContext());
+ M.reset(new llvm::Module(MainFileName, *VMContext));
+ M->setDataLayout(Ctx->getTargetInfo().getTargetDescription());
+ Builder.reset(new CodeGen::CodeGenModule(*Ctx, HeaderSearchOpts,
+ PreprocessorOpts, CodeGenOpts, *M,
+ M->getDataLayout(), Diags));
+ }
+
+ /// Emit a container holding the serialized AST.
+ void HandleTranslationUnit(ASTContext &Ctx) override {
+ assert(M && VMContext && Builder);
+ // Delete these on function exit.
+ std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
+ std::unique_ptr<llvm::Module> M = std::move(this->M);
+ std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder);
+
+ if (Diags.hasErrorOccurred())
+ return;
+
+ M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple());
+ M->setDataLayout(Ctx.getTargetInfo().getTargetDescription());
+
+ // Finalize the Builder.
+ if (Builder)
+ Builder->Release();
+
+ // Ensure the target exists.
+ std::string Error;
+ auto Triple = Ctx.getTargetInfo().getTriple();
+ if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error))
+ llvm::report_fatal_error(Error);
+
+ // Emit the serialized Clang AST into its own section.
+ assert(Buffer->IsComplete && "serialization did not complete");
+ auto &SerializedAST = Buffer->Data;
+ auto Size = SerializedAST.size();
+ auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
+ auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
+ auto *Data = llvm::ConstantDataArray::getString(
+ *VMContext, StringRef(SerializedAST.data(), Size),
+ /*AddNull=*/false);
+ auto *ASTSym = new llvm::GlobalVariable(
+ *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, Data,
+ "__clang_ast");
+ // The on-disk hashtable needs to be aligned.
+ ASTSym->setAlignment(8);
+
+ // Mach-O also needs a segment name.
+ if (Triple.isOSBinFormatMachO())
+ ASTSym->setSection("__CLANG,__clangast");
+ // COFF has an eight character length limit.
+ else if (Triple.isOSBinFormatCOFF())
+ ASTSym->setSection("clangast");
+ else
+ ASTSym->setSection("__clangast");
+
+ DEBUG({
+ // Print the IR for the PCH container to the debug output.
+ llvm::SmallString<0> Buffer;
+ llvm::raw_svector_ostream OS(Buffer);
+ clang::EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
+ Ctx.getTargetInfo().getTargetDescription(),
+ M.get(), BackendAction::Backend_EmitLL, &OS);
+ OS.flush();
+ llvm::dbgs() << Buffer;
+ });
+
+ // Use the LLVM backend to emit the pch container.
+ clang::EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
+ Ctx.getTargetInfo().getTargetDescription(),
+ M.get(), BackendAction::Backend_EmitObj, OS);
+
+ // Make sure the pch container hits disk.
+ OS->flush();
+
+ // Free the memory for the temporary buffer.
+ llvm::SmallVector<char, 0> Empty;
+ SerializedAST = std::move(Empty);
+ }
+};
+
+} // namespace
+
+std::unique_ptr<ASTConsumer>
+ObjectFilePCHContainerOperations::CreatePCHContainerGenerator(
+ DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO,
+ const PreprocessorOptions &PPO, const TargetOptions &TO,
+ const LangOptions &LO, const std::string &MainFileName,
+ const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
+ std::shared_ptr<PCHBuffer> Buffer) const {
+ return llvm::make_unique<PCHContainerGenerator>(
+ Diags, HSO, PPO, TO, LO, MainFileName, OutputFileName, OS, Buffer);
+}
+
+void ObjectFilePCHContainerOperations::ExtractPCH(
+ llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const {
+ if (auto OF = llvm::object::ObjectFile::createObjectFile(Buffer)) {
+ auto *Obj = OF.get().get();
+ bool IsCOFF = isa<llvm::object::COFFObjectFile>(Obj);
+ // Find the clang AST section in the container.
+ for (auto &Section : OF->get()->sections()) {
+ StringRef Name;
+ Section.getName(Name);
+ if ((!IsCOFF && Name == "__clangast") ||
+ ( IsCOFF && Name == "clangast")) {
+ StringRef Buf;
+ Section.getContents(Buf);
+ StreamFile.init((const unsigned char *)Buf.begin(),
+ (const unsigned char *)Buf.end());
+ return;
+ }
+ }
+ }
+
+ // As a fallback, treat the buffer as a raw AST.
+ StreamFile.init((const unsigned char *)Buffer.getBufferStart(),
+ (const unsigned char *)Buffer.getBufferEnd());
+ return;
+}
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index e5ba200e1c57..6226d213b620 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -2073,8 +2073,10 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
classify(I.getType(), Offset, FieldLo, FieldHi, isNamedArg);
Lo = merge(Lo, FieldLo);
Hi = merge(Hi, FieldHi);
- if (Lo == Memory || Hi == Memory)
- break;
+ if (Lo == Memory || Hi == Memory) {
+ postMerge(Size, Lo, Hi);
+ return;
+ }
}
}
@@ -2094,11 +2096,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
//
if (Size > 128 && getContext().getTypeSize(i->getType()) != 256) {
Lo = Memory;
+ postMerge(Size, Lo, Hi);
return;
}
// Note, skip this test for bit-fields, see below.
if (!BitField && Offset % getContext().getTypeAlign(i->getType())) {
Lo = Memory;
+ postMerge(Size, Lo, Hi);
return;
}
@@ -7095,6 +7099,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
return *(TheTargetCodeGenInfo = new PNaClTargetCodeGenInfo(Types));
case llvm::Triple::mips:
case llvm::Triple::mipsel:
+ if (Triple.getOS() == llvm::Triple::NaCl)
+ return *(TheTargetCodeGenInfo = new PNaClTargetCodeGenInfo(Types));
return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo(Types, true));
case llvm::Triple::mips64:
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index 360dbeecabf9..3219dc1cc0e9 100644
--- a/lib/Driver/Action.cpp
+++ b/lib/Driver/Action.cpp
@@ -24,6 +24,8 @@ const char *Action::getClassName(ActionClass AC) {
switch (AC) {
case InputClass: return "input";
case BindArchClass: return "bind-arch";
+ case CudaDeviceClass: return "cuda-device";
+ case CudaHostClass: return "cuda-host";
case PreprocessJobClass: return "preprocessor";
case PrecompileJobClass: return "precompiler";
case AnalyzeJobClass: return "analyzer";
@@ -53,6 +55,25 @@ BindArchAction::BindArchAction(std::unique_ptr<Action> Input,
const char *_ArchName)
: Action(BindArchClass, std::move(Input)), ArchName(_ArchName) {}
+void CudaDeviceAction::anchor() {}
+
+CudaDeviceAction::CudaDeviceAction(std::unique_ptr<Action> Input,
+ const char *ArchName, bool AtTopLevel)
+ : Action(CudaDeviceClass, std::move(Input)), GpuArchName(ArchName),
+ AtTopLevel(AtTopLevel) {}
+
+void CudaHostAction::anchor() {}
+
+CudaHostAction::CudaHostAction(std::unique_ptr<Action> Input,
+ const ActionList &_DeviceActions)
+ : Action(CudaHostClass, std::move(Input)), DeviceActions(_DeviceActions) {}
+
+CudaHostAction::~CudaHostAction() {
+ for (iterator it = DeviceActions.begin(), ie = DeviceActions.end(); it != ie;
+ ++it)
+ delete *it;
+}
+
void JobAction::anchor() {}
JobAction::JobAction(ActionClass Kind, std::unique_ptr<Action> Input,
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index b9dc35d6219a..180c412bd791 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -174,8 +174,10 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
} else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {
FinalPhase = phases::Backend;
- // -c only runs up to the assembler.
- } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {
+ // -c and partial CUDA compilations only run up to the assembler.
+ } else if ((PhaseArg = DAL.getLastArg(options::OPT_c)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_cuda_device_only)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_cuda_host_only))) {
FinalPhase = phases::Assemble;
// Otherwise do everything.
@@ -281,6 +283,83 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
return DAL;
}
+/// \brief Compute target triple from args.
+///
+/// This routine provides the logic to compute a target triple from various
+/// args passed to the driver and the default triple string.
+static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
+ const ArgList &Args,
+ StringRef DarwinArchName = "") {
+ // FIXME: Already done in Compilation *Driver::BuildCompilation
+ if (const Arg *A = Args.getLastArg(options::OPT_target))
+ DefaultTargetTriple = A->getValue();
+
+ llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple));
+
+ // Handle Apple-specific options available here.
+ if (Target.isOSBinFormatMachO()) {
+ // If an explict Darwin arch name is given, that trumps all.
+ if (!DarwinArchName.empty()) {
+ tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName);
+ return Target;
+ }
+
+ // Handle the Darwin '-arch' flag.
+ if (Arg *A = Args.getLastArg(options::OPT_arch)) {
+ StringRef ArchName = A->getValue();
+ tools::darwin::setTripleTypeForMachOArchName(Target, ArchName);
+ }
+ }
+
+ // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
+ // '-mbig-endian'/'-EB'.
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian)) {
+ if (A->getOption().matches(options::OPT_mlittle_endian)) {
+ llvm::Triple LE = Target.getLittleEndianArchVariant();
+ if (LE.getArch() != llvm::Triple::UnknownArch)
+ Target = std::move(LE);
+ } else {
+ llvm::Triple BE = Target.getBigEndianArchVariant();
+ if (BE.getArch() != llvm::Triple::UnknownArch)
+ Target = std::move(BE);
+ }
+ }
+
+ // Skip further flag support on OSes which don't support '-m32' or '-m64'.
+ if (Target.getArchName() == "tce" || Target.getOS() == llvm::Triple::Minix)
+ return Target;
+
+ // Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.
+ if (Arg *A = Args.getLastArg(options::OPT_m64, options::OPT_mx32,
+ options::OPT_m32, options::OPT_m16)) {
+ llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
+
+ if (A->getOption().matches(options::OPT_m64)) {
+ AT = Target.get64BitArchVariant().getArch();
+ if (Target.getEnvironment() == llvm::Triple::GNUX32)
+ Target.setEnvironment(llvm::Triple::GNU);
+ } else if (A->getOption().matches(options::OPT_mx32) &&
+ Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
+ AT = llvm::Triple::x86_64;
+ Target.setEnvironment(llvm::Triple::GNUX32);
+ } else if (A->getOption().matches(options::OPT_m32)) {
+ AT = Target.get32BitArchVariant().getArch();
+ if (Target.getEnvironment() == llvm::Triple::GNUX32)
+ Target.setEnvironment(llvm::Triple::GNU);
+ } else if (A->getOption().matches(options::OPT_m16) &&
+ Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
+ AT = llvm::Triple::x86;
+ Target.setEnvironment(llvm::Triple::CODE16);
+ }
+
+ if (AT != llvm::Triple::UnknownArch && AT != Target.getArch())
+ Target.setArch(AT);
+ }
+
+ return Target;
+}
+
Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
llvm::PrettyStackTraceString CrashInfo("Compilation construction");
@@ -367,7 +446,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs);
// Owned by the host.
- const ToolChain &TC = getToolChain(*UArgs);
+ const ToolChain &TC =
+ getToolChain(*UArgs, computeTargetTriple(DefaultTargetTriple, *UArgs));
// The compilation takes ownership of Args.
Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs);
@@ -398,6 +478,19 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
return C;
}
+static void printArgList(raw_ostream &OS, const llvm::opt::ArgList &Args) {
+ llvm::opt::ArgStringList ASL;
+ for (const auto *A : Args)
+ A->render(Args, ASL);
+
+ for (auto I = ASL.begin(), E = ASL.end(); I != E; ++I) {
+ if (I != ASL.begin())
+ OS << ' ';
+ Command::printArg(OS, *I, true);
+ }
+ OS << '\n';
+}
+
// When clang crashes, produce diagnostic information including the fully
// preprocessed source file(s). Request that the developer attach the
// diagnostic information to a bug report.
@@ -546,7 +639,9 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
<< "Error generating run script: " + Script + " " + EC.message();
} else {
ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n"
- << "# Original command: ";
+ << "# Driver args: ";
+ printArgList(ScriptOS, C.getInputArgs());
+ ScriptOS << "# Original command: ";
Cmd.Print(ScriptOS, "\n", /*Quote=*/true);
Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo);
Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
@@ -787,14 +882,6 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
return false;
}
-
- if (C.getArgs().hasArg(options::OPT_print_multi_os_directory)) {
- // FIXME: This should print out "lib/../lib", "lib/../lib64", or
- // "lib/../lib32" as appropriate for the toolchain. For now, print
- // nothing because it's not supported yet.
- return false;
- }
-
return true;
}
@@ -815,9 +902,20 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
} else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
os << '"' << BIA->getArchName() << '"' << ", {"
<< PrintActions1(C, *BIA->begin(), Ids) << "}";
+ } else if (CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {
+ os << '"' << CDA->getGpuArchName() << '"' << ", {"
+ << PrintActions1(C, *CDA->begin(), Ids) << "}";
} else {
+ ActionList *AL;
+ if (CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {
+ os << "{" << PrintActions1(C, *CHA->begin(), Ids) << "}"
+ << ", gpu binaries ";
+ AL = &CHA->getDeviceActions();
+ } else
+ AL = &A->getInputs();
+
const char *Prefix = "{";
- for (Action *PreRequisite : *A) {
+ for (Action *PreRequisite : *AL) {
os << Prefix << PrintActions1(C, PreRequisite, Ids);
Prefix = ", ";
}
@@ -1130,6 +1228,93 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
}
}
+// For each unique --cuda-gpu-arch= argument creates a TY_CUDA_DEVICE input
+// action and then wraps each in CudaDeviceAction paired with appropriate GPU
+// arch name. If we're only building device-side code, each action remains
+// independent. Otherwise we pass device-side actions as inputs to a new
+// CudaHostAction which combines both host and device side actions.
+static std::unique_ptr<Action>
+buildCudaActions(const Driver &D, const ToolChain &TC, DerivedArgList &Args,
+ const Arg *InputArg, const types::ID InputType,
+ std::unique_ptr<Action> Current, ActionList &Actions) {
+
+ assert(InputType == types::TY_CUDA &&
+ "CUDA Actions only apply to CUDA inputs.");
+
+ // Collect all cuda_gpu_arch parameters, removing duplicates.
+ SmallVector<const char *, 4> GpuArchList;
+ llvm::StringSet<> GpuArchNames;
+ for (Arg *A : Args) {
+ if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) {
+ A->claim();
+ if (GpuArchNames.insert(A->getValue()).second)
+ GpuArchList.push_back(A->getValue());
+ }
+ }
+
+ // Default to sm_20 which is the lowest common denominator for supported GPUs.
+ // sm_20 code should work correctly, if suboptimally, on all newer GPUs.
+ if (GpuArchList.empty())
+ GpuArchList.push_back("sm_20");
+
+ // Replicate inputs for each GPU architecture.
+ Driver::InputList CudaDeviceInputs;
+ for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i)
+ CudaDeviceInputs.push_back(std::make_pair(types::TY_CUDA_DEVICE, InputArg));
+
+ // Build actions for all device inputs.
+ ActionList CudaDeviceActions;
+ D.BuildActions(TC, Args, CudaDeviceInputs, CudaDeviceActions);
+ assert(GpuArchList.size() == CudaDeviceActions.size() &&
+ "Failed to create actions for all devices");
+
+ // Check whether any of device actions stopped before they could generate PTX.
+ bool PartialCompilation = false;
+ bool DeviceOnlyCompilation = Args.hasArg(options::OPT_cuda_device_only);
+ for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i) {
+ if (CudaDeviceActions[i]->getKind() != Action::BackendJobClass) {
+ PartialCompilation = true;
+ break;
+ }
+ }
+
+ // Figure out what to do with device actions -- pass them as inputs to the
+ // host action or run each of them independently.
+ if (PartialCompilation || DeviceOnlyCompilation) {
+ // In case of partial or device-only compilation results of device actions
+ // are not consumed by the host action device actions have to be added to
+ // top-level actions list with AtTopLevel=true and run independently.
+
+ // -o is ambiguous if we have more than one top-level action.
+ if (Args.hasArg(options::OPT_o) &&
+ (!DeviceOnlyCompilation || GpuArchList.size() > 1)) {
+ D.Diag(clang::diag::err_drv_output_argument_with_multiple_files);
+ return nullptr;
+ }
+
+ for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i)
+ Actions.push_back(
+ new CudaDeviceAction(std::unique_ptr<Action>(CudaDeviceActions[i]),
+ GpuArchList[i], /* AtTopLevel */ true));
+ // Kill host action in case of device-only compilation.
+ if (DeviceOnlyCompilation)
+ Current.reset(nullptr);
+ return Current;
+ } else {
+ // Outputs of device actions during complete CUDA compilation get created
+ // with AtTopLevel=false and become inputs for the host action.
+ ActionList DeviceActions;
+ for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i)
+ DeviceActions.push_back(
+ new CudaDeviceAction(std::unique_ptr<Action>(CudaDeviceActions[i]),
+ GpuArchList[i], /* AtTopLevel */ false));
+ // Return a new host action that incorporates original host action and all
+ // device actions.
+ return std::unique_ptr<Action>(
+ new CudaHostAction(std::move(Current), DeviceActions));
+ }
+}
+
void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
const InputList &Inputs, ActionList &Actions) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
@@ -1227,6 +1412,25 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
continue;
}
+ phases::ID CudaInjectionPhase;
+ if (isSaveTempsEnabled()) {
+ // All phases are done independently, inject GPU blobs during compilation
+ // phase as that's where we generate glue code to init them.
+ CudaInjectionPhase = phases::Compile;
+ } else {
+ // Assumes that clang does everything up until linking phase, so we inject
+ // cuda device actions at the last step before linking. Otherwise CUDA
+ // host action forces preprocessor into a separate invocation.
+ if (FinalPhase == phases::Link) {
+ for (auto i = PL.begin(), e = PL.end(); i != e; ++i) {
+ auto next = i + 1;
+ if (next != e && *next == phases::Link)
+ CudaInjectionPhase = *i;
+ }
+ } else
+ CudaInjectionPhase = FinalPhase;
+ }
+
// Build the pipeline for this file.
std::unique_ptr<Action> Current(new InputAction(*InputArg, InputType));
for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end();
@@ -1252,6 +1456,15 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
// Otherwise construct the appropriate action.
Current = ConstructPhaseAction(TC, Args, Phase, std::move(Current));
+
+ if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase &&
+ !Args.hasArg(options::OPT_cuda_host_only)) {
+ Current = buildCudaActions(*this, TC, Args, InputArg, InputType,
+ std::move(Current), Actions);
+ if (!Current)
+ break;
+ }
+
if (Current->getType() == types::TY_Nothing)
break;
}
@@ -1491,7 +1704,13 @@ static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps,
if (isa<BackendJobAction>(JA)) {
// Check if the compiler supports emitting LLVM IR.
assert(Inputs->size() == 1);
- JobAction *CompileJA = cast<CompileJobAction>(*Inputs->begin());
+ JobAction *CompileJA;
+ // Extract real host action, if it's a CudaHostAction.
+ if (CudaHostAction *CudaHA = dyn_cast<CudaHostAction>(*Inputs->begin()))
+ CompileJA = cast<CompileJobAction>(*CudaHA->begin());
+ else
+ CompileJA = cast<CompileJobAction>(*Inputs->begin());
+
const Tool *Compiler = TC->SelectTool(*CompileJA);
if (!Compiler)
return nullptr;
@@ -1525,6 +1744,20 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
InputInfo &Result) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
+ InputInfoList CudaDeviceInputInfos;
+ if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {
+ InputInfo II;
+ // Append outputs of device jobs to the input list.
+ for (const Action *DA : CHA->getDeviceActions()) {
+ BuildJobsForAction(C, DA, TC, "", AtTopLevel,
+ /*MultipleArchs*/ false, LinkingOutput, II);
+ CudaDeviceInputInfos.push_back(II);
+ }
+ // Override current action with a real host compile action and continue
+ // processing it.
+ A = *CHA->begin();
+ }
+
if (const InputAction *IA = dyn_cast<InputAction>(A)) {
// FIXME: It would be nice to not claim this here; maybe the old scheme of
// just using Args was better?
@@ -1544,15 +1777,30 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
const char *ArchName = BAA->getArchName();
if (ArchName)
- TC = &getToolChain(C.getArgs(), ArchName);
+ TC = &getToolChain(
+ C.getArgs(),
+ computeTargetTriple(DefaultTargetTriple, C.getArgs(), ArchName));
else
TC = &C.getDefaultToolChain();
- BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(), AtTopLevel,
+ BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel,
MultipleArchs, LinkingOutput, Result);
return;
}
+ if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {
+ // Figure out which NVPTX triple to use for device-side compilation based on
+ // whether host is 64-bit.
+ llvm::Triple DeviceTriple(C.getDefaultToolChain().getTriple().isArch64Bit()
+ ? "nvptx64-nvidia-cuda"
+ : "nvptx-nvidia-cuda");
+ BuildJobsForAction(C, *CDA->begin(),
+ &getToolChain(C.getArgs(), DeviceTriple),
+ CDA->getGpuArchName(), CDA->isAtTopLevel(),
+ /*MultipleArchs*/ true, LinkingOutput, Result);
+ return;
+ }
+
const ActionList *Inputs = &A->getInputs();
const JobAction *JA = cast<JobAction>(A);
@@ -1584,6 +1832,10 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
if (JA->getType() == types::TY_dSYM)
BaseInput = InputInfos[0].getFilename();
+ // Append outputs of cuda device jobs to the input list
+ if (CudaDeviceInputInfos.size())
+ InputInfos.append(CudaDeviceInputInfos.begin(), CudaDeviceInputInfos.end());
+
// Determine the place to write output to, if any.
if (JA->getType() == types::TY_Nothing)
Result = InputInfo(A->getType(), BaseInput);
@@ -1899,93 +2151,8 @@ std::string Driver::GetTemporaryPath(StringRef Prefix,
return Path.str();
}
-/// \brief Compute target triple from args.
-///
-/// This routine provides the logic to compute a target triple from various
-/// args passed to the driver and the default triple string.
-static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
- const ArgList &Args,
- StringRef DarwinArchName) {
- // FIXME: Already done in Compilation *Driver::BuildCompilation
- if (const Arg *A = Args.getLastArg(options::OPT_target))
- DefaultTargetTriple = A->getValue();
-
- llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple));
-
- // Handle Apple-specific options available here.
- if (Target.isOSBinFormatMachO()) {
- // If an explict Darwin arch name is given, that trumps all.
- if (!DarwinArchName.empty()) {
- tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName);
- return Target;
- }
-
- // Handle the Darwin '-arch' flag.
- if (Arg *A = Args.getLastArg(options::OPT_arch)) {
- StringRef ArchName = A->getValue();
- tools::darwin::setTripleTypeForMachOArchName(Target, ArchName);
- }
- }
-
- // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
- // '-mbig-endian'/'-EB'.
- if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
- options::OPT_mbig_endian)) {
- if (A->getOption().matches(options::OPT_mlittle_endian)) {
- if (Target.getArch() == llvm::Triple::mips)
- Target.setArch(llvm::Triple::mipsel);
- else if (Target.getArch() == llvm::Triple::mips64)
- Target.setArch(llvm::Triple::mips64el);
- else if (Target.getArch() == llvm::Triple::aarch64_be)
- Target.setArch(llvm::Triple::aarch64);
- } else {
- if (Target.getArch() == llvm::Triple::mipsel)
- Target.setArch(llvm::Triple::mips);
- else if (Target.getArch() == llvm::Triple::mips64el)
- Target.setArch(llvm::Triple::mips64);
- else if (Target.getArch() == llvm::Triple::aarch64)
- Target.setArch(llvm::Triple::aarch64_be);
- }
- }
-
- // Skip further flag support on OSes which don't support '-m32' or '-m64'.
- if (Target.getArchName() == "tce" || Target.getOS() == llvm::Triple::Minix)
- return Target;
-
- // Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.
- if (Arg *A = Args.getLastArg(options::OPT_m64, options::OPT_mx32,
- options::OPT_m32, options::OPT_m16)) {
- llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
-
- if (A->getOption().matches(options::OPT_m64)) {
- AT = Target.get64BitArchVariant().getArch();
- if (Target.getEnvironment() == llvm::Triple::GNUX32)
- Target.setEnvironment(llvm::Triple::GNU);
- } else if (A->getOption().matches(options::OPT_mx32) &&
- Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
- AT = llvm::Triple::x86_64;
- Target.setEnvironment(llvm::Triple::GNUX32);
- } else if (A->getOption().matches(options::OPT_m32)) {
- AT = Target.get32BitArchVariant().getArch();
- if (Target.getEnvironment() == llvm::Triple::GNUX32)
- Target.setEnvironment(llvm::Triple::GNU);
- } else if (A->getOption().matches(options::OPT_m16) &&
- Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
- AT = llvm::Triple::x86;
- Target.setEnvironment(llvm::Triple::CODE16);
- }
-
- if (AT != llvm::Triple::UnknownArch && AT != Target.getArch())
- Target.setArch(AT);
- }
-
- return Target;
-}
-
const ToolChain &Driver::getToolChain(const ArgList &Args,
- StringRef DarwinArchName) const {
- llvm::Triple Target =
- computeTargetTriple(DefaultTargetTriple, Args, DarwinArchName);
+ const llvm::Triple &Target) const {
ToolChain *&TC = ToolChains[Target.str()];
if (!TC) {
@@ -2050,6 +2217,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
break;
}
break;
+ case llvm::Triple::CUDA:
+ TC = new toolchains::CudaToolChain(*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.
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index ac18e1eb56a1..42bba56f5d41 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -71,7 +71,7 @@ static int skipArgs(const char *Flag, bool HaveCrashVFS) {
return 0;
}
-static void PrintArg(raw_ostream &OS, const char *Arg, bool Quote) {
+void Command::printArg(raw_ostream &OS, const char *Arg, bool Quote) {
const bool Escape = std::strpbrk(Arg, "\"\\$");
if (!Quote && !Escape) {
@@ -146,7 +146,7 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo) const {
// Always quote the exe.
OS << ' ';
- PrintArg(OS, Executable, /*Quote=*/true);
+ printArg(OS, Executable, /*Quote=*/true);
llvm::ArrayRef<const char *> Args = Arguments;
llvm::SmallVector<const char *, 128> ArgsRespFile;
@@ -175,20 +175,20 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
// Replace the input file name with the crashinfo's file name.
OS << ' ';
StringRef ShortName = llvm::sys::path::filename(CrashInfo->Filename);
- PrintArg(OS, ShortName.str().c_str(), Quote);
+ printArg(OS, ShortName.str().c_str(), Quote);
continue;
}
}
OS << ' ';
- PrintArg(OS, Arg, Quote);
+ printArg(OS, Arg, Quote);
}
if (CrashInfo && HaveCrashVFS) {
OS << ' ';
- PrintArg(OS, "-ivfsoverlay", Quote);
+ printArg(OS, "-ivfsoverlay", Quote);
OS << ' ';
- PrintArg(OS, CrashInfo->VFSPath.str().c_str(), Quote);
+ printArg(OS, CrashInfo->VFSPath.str().c_str(), Quote);
}
if (ResponseFile != nullptr) {
diff --git a/lib/Driver/MSVCToolChain.cpp b/lib/Driver/MSVCToolChain.cpp
index f20f58a119f4..c816b29dca23 100644
--- a/lib/Driver/MSVCToolChain.cpp
+++ b/lib/Driver/MSVCToolChain.cpp
@@ -526,8 +526,5 @@ MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
- // CFI checks are not implemented for MSVC ABI for now.
- Res &= ~SanitizerKind::CFI;
- Res &= ~SanitizerKind::CFICastStrict;
return Res;
}
diff --git a/lib/Driver/MinGWToolChain.cpp b/lib/Driver/MinGWToolChain.cpp
index 606508da6964..197c19e91413 100644
--- a/lib/Driver/MinGWToolChain.cpp
+++ b/lib/Driver/MinGWToolChain.cpp
@@ -1,5 +1,4 @@
-//===--- MinGWToolChain.cpp - MinGWToolChain Implementation
-//-----------------------===//
+//===--- MinGWToolChain.cpp - MinGWToolChain Implementation ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -25,6 +24,9 @@ MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
+ llvm::SmallString<1024> LibDir;
+
+#ifdef LLVM_ON_WIN32
if (getDriver().SysRoot.size())
Base = getDriver().SysRoot;
else if (llvm::ErrorOr<std::string> GPPName =
@@ -34,8 +36,17 @@ MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
else
Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
Base += llvm::sys::path::get_separator();
- llvm::SmallString<1024> LibDir(Base);
+ LibDir = Base;
llvm::sys::path::append(LibDir, "lib", "gcc");
+#else
+ if (getDriver().SysRoot.size())
+ Base = getDriver().SysRoot;
+ else
+ Base = "/usr/";
+ LibDir = Base;
+ llvm::sys::path::append(LibDir, "lib64", "gcc");
+#endif
+
LibDir += llvm::sys::path::get_separator();
// First look for mingw-w64.
@@ -45,6 +56,7 @@ MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
llvm::sys::fs::directory_iterator MingW64Entry(LibDir + Arch, EC);
if (!EC) {
GccLibDir = MingW64Entry->path();
+ Ver = llvm::sys::path::filename(GccLibDir);
} else {
// If mingw-w64 not found, try looking for mingw.org.
Arch = "mingw32";
@@ -58,6 +70,10 @@ MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
getFilePaths().push_back(GccLibDir);
getFilePaths().push_back(Base + "lib");
getFilePaths().push_back(Base + Arch + "lib");
+#ifdef LLVM_ON_UNIX
+ // For openSUSE.
+ getFilePaths().push_back(Base + Arch + "sys-root/mingw/lib");
+#endif
}
bool MinGW::IsIntegratedAssemblerDefault() const { return true; }
@@ -117,6 +133,11 @@ void MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
llvm::sys::path::append(IncludeDir, "include");
addSystemInclude(DriverArgs, CC1Args, IncludeDir.c_str());
IncludeDir += "-fixed";
+#ifdef LLVM_ON_UNIX
+ // For openSUSE.
+ addSystemInclude(DriverArgs, CC1Args,
+ "/usr/x86_64-w64-mingw32/sys-root/mingw/include");
+#endif
addSystemInclude(DriverArgs, CC1Args, IncludeDir.c_str());
addSystemInclude(DriverArgs, CC1Args, Base + Arch + "include");
addSystemInclude(DriverArgs, CC1Args, Base + "include");
@@ -128,16 +149,27 @@ void MinGW::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
- llvm::SmallString<1024> IncludeDir;
- for (bool MingW64 : {true, false}) {
- if (MingW64)
- IncludeDir = Base + Arch;
- else
- IncludeDir = GccLibDir;
- llvm::sys::path::append(IncludeDir, "include", "c++");
- addSystemInclude(DriverArgs, CC1Args, IncludeDir.str());
- IncludeDir += llvm::sys::path::get_separator();
- addSystemInclude(DriverArgs, CC1Args, IncludeDir.str() + Arch);
- addSystemInclude(DriverArgs, CC1Args, IncludeDir.str() + "backward");
+ // C++ includes may be found in several locations depending on distribution.
+ // Windows
+ // -------
+ // mingw-w64 mingw-builds: $sysroot/i686-w64-mingw32/include/c++.
+ // mingw-w64 msys2: $sysroot/include/c++/4.9.2
+ // mingw.org: GccLibDir/include/c++
+ //
+ // Linux
+ // -----
+ // openSUSE: GccLibDir/include/c++
+ llvm::SmallVector<llvm::SmallString<1024>, 3> CppIncludeBases;
+ CppIncludeBases.emplace_back(Base);
+ llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++");
+ CppIncludeBases.emplace_back(Base);
+ llvm::sys::path::append(CppIncludeBases[1], "include", "c++", Ver);
+ CppIncludeBases.emplace_back(GccLibDir);
+ llvm::sys::path::append(CppIncludeBases[2], "include", "c++");
+ for (auto &CppIncludeBase : CppIncludeBases) {
+ CppIncludeBase += llvm::sys::path::get_separator();
+ addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
+ addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch);
+ addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
}
}
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 3043481c7132..c3ad8ef9c1ef 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -176,6 +176,7 @@ void SanitizerArgs::clear() {
BlacklistFiles.clear();
CoverageFeatures = 0;
MsanTrackOrigins = 0;
+ MsanUseAfterDtor = false;
AsanFieldPadding = 0;
AsanZeroBaseShadow = false;
AsanSharedRuntime = false;
@@ -289,8 +290,12 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// toolchain. We don't have a good way to check the latter, so we just
// check if the toolchan supports vptr.
if (~Supported & Vptr) {
- if (SanitizerMask KindsToDiagnose =
- Kinds & ~TrappingKinds & NeedsUbsanCxxRt) {
+ SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
+ // The runtime library supports the Microsoft C++ ABI, but only well enough
+ // for CFI. FIXME: Remove this once we support vptr on Windows.
+ if (TC.getTriple().isOSWindows())
+ KindsToDiagnose &= ~CFI;
+ if (KindsToDiagnose) {
SanitizerSet S;
S.Mask = KindsToDiagnose;
D.Diag(diag::err_drv_unsupported_opt_for_target)
@@ -413,6 +418,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
}
}
+ MsanUseAfterDtor =
+ Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
}
// Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
@@ -558,6 +565,10 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
if (MsanTrackOrigins)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
llvm::utostr(MsanTrackOrigins)));
+
+ if (MsanUseAfterDtor)
+ CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-use-after-dtor"));
+
if (AsanFieldPadding)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
llvm::utostr(AsanFieldPadding)));
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index da020a2b8c9d..e6a1bc9685de 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -151,6 +151,8 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::InputClass:
case Action::BindArchClass:
+ case Action::CudaDeviceClass:
+ case Action::CudaHostClass:
case Action::LipoJobClass:
case Action::DsymutilJobClass:
case Action::VerifyDebugInfoJobClass:
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index df74b41b0225..15e36a1e6ce0 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -303,6 +303,7 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
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) ||
@@ -2337,6 +2338,13 @@ NaCl_TC::NaCl_TC(const Driver &D, const llvm::Triple &Triple,
file_paths.push_back(ToolPath + "arm-nacl");
break;
}
+ case llvm::Triple::mipsel: {
+ file_paths.push_back(FilePath + "mipsel-nacl/lib");
+ file_paths.push_back(FilePath + "mipsel-nacl/usr/lib");
+ prog_paths.push_back(ProgPath + "bin");
+ file_paths.push_back(ToolPath + "mipsel-nacl");
+ break;
+ }
default:
break;
}
@@ -2372,6 +2380,9 @@ void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
case llvm::Triple::x86_64:
llvm::sys::path::append(P, "x86_64-nacl/usr/include");
break;
+ case llvm::Triple::mipsel:
+ llvm::sys::path::append(P, "mipsel-nacl/usr/include");
+ break;
default:
return;
}
@@ -2416,6 +2427,10 @@ void NaCl_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
addSystemInclude(DriverArgs, CC1Args, P.str());
break;
+ case llvm::Triple::mipsel:
+ llvm::sys::path::append(P, "mipsel-nacl/include/c++/v1");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ break;
default:
break;
}
@@ -2868,6 +2883,7 @@ enum Distro {
UbuntuTrusty,
UbuntuUtopic,
UbuntuVivid,
+ UbuntuWily,
UnknownDistro
};
@@ -2882,7 +2898,7 @@ static bool IsDebian(enum Distro Distro) {
}
static bool IsUbuntu(enum Distro Distro) {
- return Distro >= UbuntuHardy && Distro <= UbuntuVivid;
+ return Distro >= UbuntuHardy && Distro <= UbuntuWily;
}
static Distro DetectDistro(llvm::Triple::ArchType Arch) {
@@ -2911,6 +2927,7 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
.Case("trusty", UbuntuTrusty)
.Case("utopic", UbuntuUtopic)
.Case("vivid", UbuntuVivid)
+ .Case("wily", UbuntuWily)
.Default(UnknownDistro);
return Version;
}
@@ -3635,6 +3652,65 @@ Tool *DragonFly::buildLinker() const {
return new tools::dragonfly::Linker(*this);
}
+/// Stub for CUDA toolchain. At the moment we don't have assembler or
+/// linker and need toolchain mainly to propagate device-side options
+/// to CC1.
+
+CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Linux(D, Triple, Args) {}
+
+void
+CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ Linux::addClangTargetOptions(DriverArgs, CC1Args);
+ CC1Args.push_back("-fcuda-is-device");
+}
+
+llvm::opt::DerivedArgList *
+CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ const OptTable &Opts = getDriver().getOpts();
+
+ for (Arg *A : Args) {
+ if (A->getOption().matches(options::OPT_Xarch__)) {
+ // Skip this argument unless the architecture matches BoundArch
+ if (A->getValue(0) != StringRef(BoundArch))
+ continue;
+
+ unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
+ unsigned Prev = Index;
+ std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
+
+ // If the argument parsing failed or more than one argument was
+ // consumed, the -Xarch_ argument's parameter tried to consume
+ // extra arguments. Emit an error and ignore.
+ //
+ // We also want to disallow any options which would alter the
+ // driver behavior; that isn't going to work in our model. We
+ // use isDriverOption() as an approximation, although things
+ // like -O4 are going to slip through.
+ if (!XarchArg || Index > Prev + 1) {
+ getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
+ << A->getAsString(Args);
+ continue;
+ } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
+ getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
+ << A->getAsString(Args);
+ continue;
+ }
+ XarchArg->setBaseArg(A);
+ A = XarchArg.release();
+ DAL->AddSynthesizedArg(A);
+ }
+ DAL->append(A);
+ }
+
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
+ return DAL;
+}
+
/// XCore tool chain
XCore::XCore(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) {
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 629f90ac79f8..327ff9b13b19 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -552,6 +552,7 @@ protected:
private:
std::string Base;
std::string GccLibDir;
+ std::string Ver;
std::string Arch;
mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocessor;
mutable std::unique_ptr<tools::gcc::Compiler> Compiler;
@@ -698,6 +699,18 @@ private:
std::string computeSysRoot() const;
};
+class LLVM_LIBRARY_VISIBILITY CudaToolChain : public Linux {
+public:
+ CudaToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const override;
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+};
+
class LLVM_LIBRARY_VISIBILITY Hexagon_TC : public Linux {
protected:
GCCVersion GCCLibAndIncVersion;
@@ -746,7 +759,9 @@ public:
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
- bool IsIntegratedAssemblerDefault() const override { return false; }
+ bool IsIntegratedAssemblerDefault() const override {
+ return getTriple().getArch() == llvm::Triple::mipsel;
+ }
// Get the path to the file containing NaCl's ARM macros. It lives in NaCl_TC
// because the AssembleARM tool needs a const char * that it can pass around
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index a2955dbb9e77..8c11992f1f82 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -638,6 +638,8 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<const char *> &Features,
bool ForAS) {
+ bool KernelOrKext =
+ Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
if (!ForAS) {
// FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
@@ -705,6 +707,17 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_1a) {
Features.insert(Features.begin(), "+v8.1a");
}
+
+ // 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.
+ if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
+ options::OPT_mno_long_calls)) {
+ if (A->getOption().matches(options::OPT_mlong_calls))
+ Features.push_back("+long-calls");
+ } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6))) {
+ Features.push_back("+long-calls");
+ }
}
void Clang::AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
@@ -778,11 +791,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
// Kernel code has more strict alignment requirements.
if (KernelOrKext) {
- if (!Triple.isiOS() || Triple.isOSVersionLT(6)) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-long-calls");
- }
-
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-arm-strict-align");
@@ -1264,9 +1272,7 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Select the ABI to use.
const char *ABIName = nullptr;
- if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
- ABIName = A->getValue();
- } else if (getToolChain().getTriple().isOSLinux())
+ if (getToolChain().getTriple().isOSLinux())
switch (getToolChain().getArch()) {
case llvm::Triple::ppc64: {
// When targeting a processor that supports QPX, or if QPX is
@@ -1291,6 +1297,13 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
break;
}
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ // The ppc64 linux abis are all "altivec" abis by default. Accept and ignore
+ // the option if given as we don't have backend support for any targets
+ // that don't use the altivec abi.
+ if (StringRef(A->getValue()) != "altivec")
+ ABIName = A->getValue();
+
if (ABIName) {
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
@@ -1475,6 +1488,12 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
return CPUName;
}
+ case llvm::Triple::nvptx:
+ case llvm::Triple::nvptx64:
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ return A->getValue();
+ return "";
+
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le: {
@@ -2028,17 +2047,6 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
Triple.getArch() == llvm::Triple::arm));
}
-// exceptionSettings() exists to share the logic between -cc1 and linker
-// invocations.
-static bool exceptionSettings(const ArgList &Args, const llvm::Triple &Triple) {
- if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
- options::OPT_fno_exceptions))
- if (A->getOption().matches(options::OPT_fexceptions))
- return true;
-
- return false;
-}
-
/// Adds exception related arguments to the driver command arguments. There's a
/// master flag, -fexceptions and also language specific flags to enable/disable
/// C++ and Objective-C exceptions. This makes it possible to for example
@@ -2062,8 +2070,9 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
return;
}
- // Gather the exception settings from the command line arguments.
- bool EH = exceptionSettings(Args, Triple);
+ // See if the user explicitly enabled exceptions.
+ bool EH = Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
+ false);
// Obj-C exceptions are enabled by default, regardless of -fexceptions. This
// is not necessarily sensible, but follows GCC.
@@ -2076,8 +2085,11 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
}
if (types::isCXX(InputType)) {
- bool CXXExceptionsEnabled =
- Triple.getArch() != llvm::Triple::xcore && !Triple.isPS4CPU();
+ // Disable C++ EH by default on XCore, PS4, and MSVC.
+ // FIXME: Remove MSVC from this list once things work.
+ bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore &&
+ !Triple.isPS4CPU() &&
+ !Triple.isWindowsMSVCEnvironment();
Arg *ExceptionArg = Args.getLastArg(
options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
options::OPT_fexceptions, options::OPT_fno_exceptions);
@@ -2290,6 +2302,7 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args,
if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
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) ||
@@ -2723,6 +2736,89 @@ VersionTuple visualstudio::getMSVCVersion(const Driver *D,
return VersionTuple();
}
+static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
+ const InputInfo &Output, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ auto *ProfileGenerateArg = Args.getLastArg(
+ options::OPT_fprofile_instr_generate,
+ options::OPT_fprofile_instr_generate_EQ, options::OPT_fprofile_generate,
+ options::OPT_fprofile_generate_EQ);
+
+ auto *ProfileUseArg = Args.getLastArg(
+ options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ,
+ options::OPT_fprofile_use, options::OPT_fprofile_use_EQ);
+
+ if (ProfileGenerateArg && ProfileUseArg)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << ProfileGenerateArg->getSpelling()
+ << ProfileUseArg->getSpelling();
+
+ if (ProfileGenerateArg &&
+ ProfileGenerateArg->getOption().matches(
+ options::OPT_fprofile_instr_generate_EQ))
+ ProfileGenerateArg->render(Args, CmdArgs);
+ else if (ProfileGenerateArg &&
+ ProfileGenerateArg->getOption().matches(
+ options::OPT_fprofile_generate_EQ)) {
+ SmallString<128> Path(ProfileGenerateArg->getValue());
+ llvm::sys::path::append(Path, "default.profraw");
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-fprofile-instr-generate=") + Path));
+ } else
+ Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);
+
+ if (ProfileUseArg &&
+ ProfileUseArg->getOption().matches(options::OPT_fprofile_instr_use_EQ))
+ ProfileUseArg->render(Args, CmdArgs);
+ else if (ProfileUseArg &&
+ (ProfileUseArg->getOption().matches(options::OPT_fprofile_use_EQ) ||
+ ProfileUseArg->getOption().matches(
+ options::OPT_fprofile_instr_use))) {
+ SmallString<128> Path(
+ ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
+ if (Path.empty() || llvm::sys::fs::is_directory(Path))
+ llvm::sys::path::append(Path, "default.profdata");
+ CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-instr-use=") + Path));
+ }
+
+ if (Args.hasArg(options::OPT_ftest_coverage) ||
+ Args.hasArg(options::OPT_coverage))
+ CmdArgs.push_back("-femit-coverage-notes");
+ if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
+ false) ||
+ Args.hasArg(options::OPT_coverage))
+ CmdArgs.push_back("-femit-coverage-data");
+
+ if (Args.hasArg(options::OPT_fcoverage_mapping) && !ProfileGenerateArg)
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << "-fcoverage-mapping"
+ << "-fprofile-instr-generate";
+
+ if (Args.hasArg(options::OPT_fcoverage_mapping))
+ CmdArgs.push_back("-fcoverage-mapping");
+
+ if (C.getArgs().hasArg(options::OPT_c) ||
+ C.getArgs().hasArg(options::OPT_S)) {
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-coverage-file");
+ SmallString<128> CoverageFilename;
+ if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) {
+ CoverageFilename = FinalOutput->getValue();
+ } else {
+ CoverageFilename = llvm::sys::path::filename(Output.getBaseInput());
+ }
+ if (llvm::sys::path::is_relative(CoverageFilename)) {
+ SmallString<128> Pwd;
+ if (!llvm::sys::fs::current_path(Pwd)) {
+ llvm::sys::path::append(Pwd, CoverageFilename);
+ CoverageFilename.swap(Pwd);
+ }
+ }
+ CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
+ }
+ }
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
@@ -2736,8 +2832,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getTriple().isWindowsCygwinEnvironment();
bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();
- assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+ // 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 compilation may have multiple inputs (source file + results of
+ // device-side compilations). All other jobs are expected to have exactly one
+ // input.
+ bool IsCuda = types::isCuda(Input.getType());
+ assert((IsCuda || Inputs.size() == 1) && "Unable to handle multiple inputs.");
// Invoke ourselves in -cc1 mode.
//
@@ -2805,6 +2907,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");
+ if (JA.getType() == types::TY_LTO_IR ||
+ JA.getType() == types::TY_LTO_BC) {
+ CmdArgs.push_back("-flto");
+ }
if (JA.getType() == types::TY_Nothing) {
CmdArgs.push_back("-fsyntax-only");
} else if (JA.getType() == types::TY_LLVM_IR ||
@@ -3520,62 +3626,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
- if ((Args.hasArg(options::OPT_fprofile_instr_generate) ||
- Args.hasArg(options::OPT_fprofile_instr_generate_EQ)) &&
- (Args.hasArg(options::OPT_fprofile_instr_use) ||
- Args.hasArg(options::OPT_fprofile_instr_use_EQ)))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fprofile-instr-generate"
- << "-fprofile-instr-use";
-
- if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_generate_EQ))
- A->render(Args, CmdArgs);
- else
- Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);
-
- if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_use_EQ))
- A->render(Args, CmdArgs);
- else if (Args.hasArg(options::OPT_fprofile_instr_use))
- CmdArgs.push_back("-fprofile-instr-use=pgo-data");
-
- if (Args.hasArg(options::OPT_ftest_coverage) ||
- Args.hasArg(options::OPT_coverage))
- CmdArgs.push_back("-femit-coverage-notes");
- if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
- false) ||
- Args.hasArg(options::OPT_coverage))
- CmdArgs.push_back("-femit-coverage-data");
-
- if (Args.hasArg(options::OPT_fcoverage_mapping) &&
- !(Args.hasArg(options::OPT_fprofile_instr_generate) ||
- Args.hasArg(options::OPT_fprofile_instr_generate_EQ)))
- D.Diag(diag::err_drv_argument_only_allowed_with)
- << "-fcoverage-mapping"
- << "-fprofile-instr-generate";
-
- if (Args.hasArg(options::OPT_fcoverage_mapping))
- CmdArgs.push_back("-fcoverage-mapping");
-
- if (C.getArgs().hasArg(options::OPT_c) ||
- C.getArgs().hasArg(options::OPT_S)) {
- if (Output.isFilename()) {
- CmdArgs.push_back("-coverage-file");
- SmallString<128> CoverageFilename;
- if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) {
- CoverageFilename = FinalOutput->getValue();
- } else {
- CoverageFilename = llvm::sys::path::filename(Output.getBaseInput());
- }
- if (llvm::sys::path::is_relative(CoverageFilename)) {
- SmallString<128> Pwd;
- if (!llvm::sys::fs::current_path(Pwd)) {
- llvm::sys::path::append(Pwd, CoverageFilename);
- CoverageFilename.swap(Pwd);
- }
- }
- CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
- }
- }
+ addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
// Pass options for controlling the default header search paths.
if (Args.hasArg(options::OPT_nostdinc)) {
@@ -3915,6 +3966,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
case OMPRT_IOMP5:
// Clang can generate useful OpenMP code for these two runtime libraries.
CmdArgs.push_back("-fopenmp");
+
+ // If no option regarding the use of TLS in OpenMP codegeneration is
+ // given, decide a default based on the target. Otherwise rely on the
+ // options and pass the right information to the frontend.
+ if (!Args.hasFlag(options::OPT_fopenmp_use_tls,
+ options::OPT_fnoopenmp_use_tls,
+ getToolChain().getArch() == llvm::Triple::ppc ||
+ getToolChain().getArch() == llvm::Triple::ppc64 ||
+ getToolChain().getArch() == llvm::Triple::ppc64le))
+ CmdArgs.push_back("-fnoopenmp-use-tls");
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
@@ -4070,17 +4131,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-arm-restrict-it");
}
- if (TT.getArch() == llvm::Triple::arm ||
- TT.getArch() == llvm::Triple::thumb) {
- if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
- options::OPT_mno_long_calls)) {
- if (A->getOption().matches(options::OPT_mlong_calls)) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-long-calls");
- }
- }
- }
-
// Forward -f options with positive and negative forms; we translate
// these by hand.
if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) {
@@ -4172,27 +4222,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fmodule-cache-path specifies where our implicitly-built module files
// should be written.
- SmallString<128> ModuleCachePath;
+ SmallString<128> Path;
if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
- ModuleCachePath = A->getValue();
+ Path = A->getValue();
if (HaveModules) {
if (C.isForDiagnostics()) {
// When generating crash reports, we want to emit the modules along with
// the reproduction sources, so we ignore any provided module path.
- ModuleCachePath = Output.getFilename();
- llvm::sys::path::replace_extension(ModuleCachePath, ".cache");
- llvm::sys::path::append(ModuleCachePath, "modules");
- } else if (ModuleCachePath.empty()) {
+ Path = Output.getFilename();
+ llvm::sys::path::replace_extension(Path, ".cache");
+ llvm::sys::path::append(Path, "modules");
+ } else if (Path.empty()) {
// No module path was provided: use the default.
llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
- ModuleCachePath);
- llvm::sys::path::append(ModuleCachePath, "org.llvm.clang.");
- appendUserToPath(ModuleCachePath);
- llvm::sys::path::append(ModuleCachePath, "ModuleCache");
+ Path);
+ llvm::sys::path::append(Path, "org.llvm.clang.");
+ appendUserToPath(Path);
+ llvm::sys::path::append(Path, "ModuleCache");
}
const char Arg[] = "-fmodules-cache-path=";
- ModuleCachePath.insert(ModuleCachePath.begin(), Arg, Arg + strlen(Arg));
- CmdArgs.push_back(Args.MakeArgString(ModuleCachePath));
+ Path.insert(Path.begin(), Arg, Arg + strlen(Arg));
+ CmdArgs.push_back(Args.MakeArgString(Path));
}
// When building modules and generating crashdumps, we need to dump a module
@@ -4774,14 +4824,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- for (const auto &II : Inputs) {
- addDashXForInput(Args, II, CmdArgs);
+ addDashXForInput(Args, Input, CmdArgs);
- if (II.isFilename())
- CmdArgs.push_back(II.getFilename());
- else
- II.getInputArg().renderAsInput(Args, CmdArgs);
- }
+ if (Input.isFilename())
+ CmdArgs.push_back(Input.getFilename());
+ else
+ Input.getInputArg().renderAsInput(Args, CmdArgs);
Args.AddAllArgs(CmdArgs, options::OPT_undef);
@@ -4819,6 +4867,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(SplitDwarfOut);
}
+ // Host-side cuda compilation receives device-side outputs as Inputs[1...].
+ // Include them with -fcuda-include-gpubinary.
+ if (IsCuda && Inputs.size() > 1)
+ for (InputInfoList::const_iterator it = std::next(Inputs.begin()),
+ ie = Inputs.end();
+ it != ie; ++it) {
+ CmdArgs.push_back("-fcuda-include-gpubinary");
+ CmdArgs.push_back(it->getFilename());
+ }
+
// Finally add the compile command to the compilation.
if (Args.hasArg(options::OPT__SLASH_fallback) &&
Output.getType() == types::TY_Object &&
@@ -5005,6 +5063,7 @@ struct EHFlags {
/// The default is /EHs-c-, meaning cleanups are disabled.
static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
EHFlags EH;
+
std::vector<std::string> EHArgs =
Args.getAllArgValues(options::OPT__SLASH_EH);
for (auto EHVal : EHArgs) {
@@ -5026,6 +5085,11 @@ static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
break;
}
}
+
+ // FIXME: Disable C++ EH completely, until it becomes more reliable. Users
+ // can use -Xclang to manually enable C++ EH until then.
+ EH = EHFlags();
+
return EH;
}
@@ -8199,6 +8263,8 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("armelf_nacl");
else if (Arch == llvm::Triple::x86_64)
CmdArgs.push_back("elf_x86_64_nacl");
+ else if (Arch == llvm::Triple::mipsel)
+ CmdArgs.push_back("mipselelf_nacl");
else
D.Diag(diag::err_target_unsupported_arch) << ToolChain.getArchName()
<< "Native Client";
@@ -8260,6 +8326,13 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// in the group for C++.
if (Args.hasArg(options::OPT_pthread) ||
Args.hasArg(options::OPT_pthreads) || D.CCCIsCXX()) {
+ // Gold, used by Mips, handles nested groups differently than ld, and
+ // without '-lnacl' it prefers symbols from libpthread.a over libnacl.a,
+ // which is not a desired behaviour here.
+ // See https://sourceware.org/ml/binutils/2015-03/msg00034.html
+ if (getToolChain().getArch() == llvm::Triple::mipsel)
+ CmdArgs.push_back("-lnacl");
+
CmdArgs.push_back("-lpthread");
}
@@ -8270,6 +8343,13 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-lgcc_s");
CmdArgs.push_back("--no-as-needed");
+
+ // Mips needs to create and use pnacl_legacy library that contains
+ // definitions from bitcode/pnaclmm.c and definitions for
+ // __nacl_tp_tls_offset() and __nacl_tp_tdb_offset().
+ if (getToolChain().getArch() == llvm::Triple::mipsel)
+ CmdArgs.push_back("-lpnacl_legacy");
+
CmdArgs.push_back("--end-group");
}
@@ -8863,6 +8943,12 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
+ StringRef LinkerName = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "ld");
+ if (LinkerName.equals_lower("lld")) {
+ CmdArgs.push_back("-flavor");
+ CmdArgs.push_back("gnu");
+ }
+
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
@@ -8874,6 +8960,8 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("i386pe");
if (TC.getArch() == llvm::Triple::x86_64)
CmdArgs.push_back("i386pep");
+ if (TC.getArch() == llvm::Triple::arm)
+ CmdArgs.push_back("thumb2pe");
if (Args.hasArg(options::OPT_mwindows)) {
CmdArgs.push_back("--subsystem");
@@ -8968,10 +9056,8 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lgmon");
- // FIXME: what to do about pthreads library?
- // Currently required for OpenMP and posix-threading libgcc,
- // does not exists in mingw.org.
- //CmdArgs.push_back("-lpthread");
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-lpthread");
// add system libraries
if (Args.hasArg(options::OPT_mwindows)) {
@@ -8985,7 +9071,7 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("--end-group");
- else
+ else if (!LinkerName.equals_lower("lld"))
AddLibGCC(Args, CmdArgs);
}
@@ -8996,7 +9082,7 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
}
}
- const char *Exec = Args.MakeArgString(TC.GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(TC.GetProgramPath(LinkerName.data()));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
@@ -9053,7 +9139,9 @@ void XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_v))
CmdArgs.push_back("-v");
- if (exceptionSettings(Args, getToolChain().getTriple()))
+ // Pass -fexceptions through to the linker if it was present.
+ if (Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
+ false))
CmdArgs.push_back("-fexceptions");
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index 7b281457557b..2085b0124298 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -86,6 +86,7 @@ bool types::isAcceptedByClang(ID Id) {
case TY_C: case TY_PP_C:
case TY_CL:
case TY_CUDA: case TY_PP_CUDA:
+ case TY_CUDA_DEVICE:
case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
case TY_CXX: case TY_PP_CXX:
case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
@@ -122,7 +123,19 @@ bool types::isCXX(ID Id) {
case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
case TY_CXXHeader: case TY_PP_CXXHeader:
case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
- case TY_CUDA: case TY_PP_CUDA:
+ case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE:
+ return true;
+ }
+}
+
+bool types::isCuda(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_CUDA:
+ case TY_PP_CUDA:
+ case TY_CUDA_DEVICE:
return true;
}
}
@@ -206,10 +219,12 @@ void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
P.push_back(phases::Compile);
P.push_back(phases::Backend);
}
- P.push_back(phases::Assemble);
+ if (Id != TY_CUDA_DEVICE)
+ P.push_back(phases::Assemble);
}
}
- if (!onlyPrecompileType(Id)) {
+
+ if (!onlyPrecompileType(Id) && Id != TY_CUDA_DEVICE) {
P.push_back(phases::Link);
}
assert(0 < P.size() && "Not enough phases in list");
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index ed01d689c590..dd56831a3bc5 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -628,7 +628,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return State.Stack.back().Indent;
if (NextNonComment->isOneOf(TT_StartOfName, TT_PointerOrReference) ||
- Previous.isOneOf(tok::coloncolon, tok::equal))
+ Previous.isOneOf(tok::coloncolon, tok::equal, TT_JsTypeColon))
return ContinuationIndent;
if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral))
@@ -862,6 +862,8 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
unsigned LastSpace = State.Stack.back().LastSpace;
bool AvoidBinPacking;
bool BreakBeforeParameter = false;
+ unsigned NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall,
+ State.Stack.back().NestedBlockIndent);
if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) {
if (Current.opensBlockTypeList(Style)) {
NewIndent = State.Stack.back().NestedBlockIndent + Style.IndentWidth;
@@ -875,6 +877,8 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
Current.isOneOf(TT_ArrayInitializerLSquare, TT_DictLiteral) ||
Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments ||
(NextNoComment && NextNoComment->is(TT_DesignatedInitializerPeriod));
+ if (Current.ParameterCount > 1)
+ NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
} else {
NewIndent = Style.ContinuationIndentWidth +
std::max(State.Stack.back().LastSpace,
@@ -922,8 +926,6 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
bool NoLineBreak = State.Stack.back().NoLineBreak ||
(Current.is(TT_TemplateOpener) &&
State.Stack.back().ContainsUnwrappedBuilder);
- unsigned NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall,
- State.Stack.back().NestedBlockIndent);
State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, LastSpace,
AvoidBinPacking, NoLineBreak));
State.Stack.back().NestedBlockIndent = NestedBlockIndent;
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 2bbe4c63d156..382ae819ebfd 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Regex.h"
#include "llvm/Support/YAMLTraits.h"
#include <queue>
#include <string>
@@ -93,6 +94,7 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
+ IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
@@ -244,6 +246,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.IndentWrappedFunctionNames);
IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
Style.KeepEmptyLinesAtTheStartOfBlocks);
+ IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
+ IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
@@ -468,6 +472,8 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
ChromiumStyle.BinPackParameters = false;
ChromiumStyle.DerivePointerAlignment = false;
}
+ ChromiumStyle.MacroBlockBegin = "^IPC_BEGIN_MESSAGE_MAP$";
+ ChromiumStyle.MacroBlockBegin = "^IPC_END_MESSAGE_MAP$";
return ChromiumStyle;
}
@@ -478,6 +484,7 @@ FormatStyle getMozillaStyle() {
MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
FormatStyle::DRTBS_TopLevel;
MozillaStyle.AlwaysBreakTemplateDeclarations = true;
+ MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
MozillaStyle.BreakConstructorInitializersBeforeComma = true;
MozillaStyle.ConstructorInitializerIndentWidth = 2;
MozillaStyle.ContinuationIndentWidth = 2;
@@ -620,7 +627,9 @@ public:
LessStashed(false), Column(0), TrailingWhitespace(0),
SourceMgr(SourceMgr), ID(ID), Style(Style),
IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
- Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false) {
+ Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
+ MacroBlockBeginRegex(Style.MacroBlockBegin),
+ MacroBlockEndRegex(Style.MacroBlockEnd) {
Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
getFormattingLangOpts(Style)));
Lex->SetKeepWhitespaceMode(true);
@@ -1168,12 +1177,21 @@ private:
Column = FormatTok->LastLineColumnWidth;
}
- 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;
+ if (Style.Language == FormatStyle::LK_Cpp) {
+ 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;
+ } else if (FormatTok->is(tok::identifier)) {
+ if (MacroBlockBeginRegex.match(Text)) {
+ FormatTok->Type = TT_MacroBlockBegin;
+ } else if (MacroBlockEndRegex.match(Text)) {
+ FormatTok->Type = TT_MacroBlockEnd;
+ }
+ }
+ }
return FormatTok;
}
@@ -1198,6 +1216,9 @@ private:
bool FormattingDisabled;
+ llvm::Regex MacroBlockBeginRegex;
+ llvm::Regex MacroBlockEndRegex;
+
void readRawToken(FormatToken &Tok) {
Lex->LexFromRawLexer(Tok.Tok);
Tok.TokenText = StringRef(SourceMgr.getCharacterData(Tok.Tok.getLocation()),
diff --git a/lib/Format/FormatToken.cpp b/lib/Format/FormatToken.cpp
index 316171dc1891..6c244c316604 100644
--- a/lib/Format/FormatToken.cpp
+++ b/lib/Format/FormatToken.cpp
@@ -23,6 +23,20 @@
namespace clang {
namespace format {
+const char *getTokenTypeName(TokenType Type) {
+ static const char *const TokNames[] = {
+#define TYPE(X) #X,
+LIST_TOKEN_TYPES
+#undef TYPE
+ nullptr
+ };
+
+ if (Type < NUM_TOKEN_TYPES)
+ return TokNames[Type];
+ llvm_unreachable("unknown TokenType");
+ return nullptr;
+}
+
// FIXME: This is copy&pasted from Sema. Put it in a common place and remove
// duplication.
bool FormatToken::isSimpleTypeSpecifier() const {
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index 5b7dadb8545b..f335eda086c0 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -25,66 +25,77 @@
namespace clang {
namespace format {
+#define LIST_TOKEN_TYPES \
+ TYPE(ArrayInitializerLSquare) \
+ TYPE(ArraySubscriptLSquare) \
+ TYPE(AttributeParen) \
+ TYPE(BinaryOperator) \
+ TYPE(BitFieldColon) \
+ TYPE(BlockComment) \
+ TYPE(CastRParen) \
+ TYPE(ConditionalExpr) \
+ TYPE(ConflictAlternative) \
+ TYPE(ConflictEnd) \
+ TYPE(ConflictStart) \
+ TYPE(CtorInitializerColon) \
+ TYPE(CtorInitializerComma) \
+ TYPE(DesignatedInitializerPeriod) \
+ TYPE(DictLiteral) \
+ TYPE(ForEachMacro) \
+ TYPE(FunctionAnnotationRParen) \
+ TYPE(FunctionDeclarationName) \
+ TYPE(FunctionLBrace) \
+ TYPE(FunctionTypeLParen) \
+ TYPE(ImplicitStringLiteral) \
+ TYPE(InheritanceColon) \
+ TYPE(InlineASMBrace) \
+ TYPE(InlineASMColon) \
+ TYPE(JavaAnnotation) \
+ TYPE(JsComputedPropertyName) \
+ TYPE(JsFatArrow) \
+ TYPE(JsTypeColon) \
+ TYPE(JsTypeOptionalQuestion) \
+ TYPE(LambdaArrow) \
+ TYPE(LambdaLSquare) \
+ TYPE(LeadingJavaAnnotation) \
+ TYPE(LineComment) \
+ TYPE(MacroBlockBegin) \
+ TYPE(MacroBlockEnd) \
+ TYPE(ObjCBlockLBrace) \
+ TYPE(ObjCBlockLParen) \
+ TYPE(ObjCDecl) \
+ TYPE(ObjCForIn) \
+ TYPE(ObjCMethodExpr) \
+ TYPE(ObjCMethodSpecifier) \
+ TYPE(ObjCProperty) \
+ TYPE(ObjCStringLiteral) \
+ TYPE(OverloadedOperator) \
+ TYPE(OverloadedOperatorLParen) \
+ TYPE(PointerOrReference) \
+ TYPE(PureVirtualSpecifier) \
+ TYPE(RangeBasedForLoopColon) \
+ TYPE(RegexLiteral) \
+ TYPE(SelectorName) \
+ TYPE(StartOfName) \
+ TYPE(TemplateCloser) \
+ TYPE(TemplateOpener) \
+ TYPE(TemplateString) \
+ TYPE(TrailingAnnotation) \
+ TYPE(TrailingReturnArrow) \
+ TYPE(TrailingUnaryOperator) \
+ TYPE(UnaryOperator) \
+ TYPE(Unknown)
+
enum TokenType {
- TT_ArrayInitializerLSquare,
- TT_ArraySubscriptLSquare,
- TT_AttributeParen,
- TT_BinaryOperator,
- TT_BitFieldColon,
- TT_BlockComment,
- TT_CastRParen,
- TT_ConditionalExpr,
- TT_ConflictAlternative,
- TT_ConflictEnd,
- TT_ConflictStart,
- TT_CtorInitializerColon,
- TT_CtorInitializerComma,
- TT_DesignatedInitializerPeriod,
- TT_DictLiteral,
- TT_ForEachMacro,
- TT_FunctionAnnotationRParen,
- TT_FunctionDeclarationName,
- TT_FunctionLBrace,
- TT_FunctionTypeLParen,
- TT_ImplicitStringLiteral,
- TT_InheritanceColon,
- TT_InlineASMBrace,
- TT_InlineASMColon,
- TT_JavaAnnotation,
- TT_JsComputedPropertyName,
- TT_JsFatArrow,
- TT_JsTypeColon,
- TT_JsTypeOptionalQuestion,
- TT_LambdaArrow,
- TT_LambdaLSquare,
- TT_LeadingJavaAnnotation,
- TT_LineComment,
- TT_ObjCBlockLBrace,
- TT_ObjCBlockLParen,
- TT_ObjCDecl,
- TT_ObjCForIn,
- TT_ObjCMethodExpr,
- TT_ObjCMethodSpecifier,
- TT_ObjCProperty,
- TT_ObjCStringLiteral,
- TT_OverloadedOperator,
- TT_OverloadedOperatorLParen,
- TT_PointerOrReference,
- TT_PureVirtualSpecifier,
- TT_RangeBasedForLoopColon,
- TT_RegexLiteral,
- TT_SelectorName,
- TT_StartOfName,
- TT_TemplateCloser,
- TT_TemplateOpener,
- TT_TemplateString,
- TT_TrailingAnnotation,
- TT_TrailingReturnArrow,
- TT_TrailingUnaryOperator,
- TT_UnaryOperator,
- TT_Unknown
+#define TYPE(X) TT_##X,
+LIST_TOKEN_TYPES
+#undef TYPE
+ NUM_TOKEN_TYPES
};
+/// \brief Determines the name of a token type.
+const char *getTokenTypeName(TokenType Type);
+
// Represents what type of block a set of braces open.
enum BraceBlockKind { BK_Unknown, BK_Block, BK_BracedInit };
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 0e1f14ad05f2..ea8b30de8dfb 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -505,7 +505,8 @@ private:
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
!Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
(!Tok->Previous ||
- !Tok->Previous->isOneOf(tok::kw_decltype, TT_LeadingJavaAnnotation)))
+ !Tok->Previous->isOneOf(tok::kw_decltype, tok::kw___attribute,
+ TT_LeadingJavaAnnotation)))
Line.MightBeFunctionDecl = true;
break;
case tok::l_square:
@@ -1627,6 +1628,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
} else if (Style.Language == FormatStyle::LK_JavaScript) {
if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma))
return 100;
+ if (Left.is(TT_JsTypeColon))
+ return 100;
}
if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
@@ -1705,7 +1708,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::l_paren) && InFunctionDecl && Style.AlignAfterOpenBracket)
return 100;
- if (Left.is(tok::l_paren) && Left.Previous && Left.Previous->is(tok::kw_if))
+ if (Left.is(tok::l_paren) && Left.Previous &&
+ Left.Previous->isOneOf(tok::kw_if, tok::kw_for))
return 1000;
if (Left.is(tok::equal) && InFunctionDecl)
return 110;
@@ -2104,7 +2108,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return Right.HasUnescapedNewline;
if (isAllmanBrace(Left) || isAllmanBrace(Right))
return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU;
+ Style.BreakBeforeBraces == FormatStyle::BS_GNU ||
+ (Style.BreakBeforeBraces == FormatStyle::BS_Mozilla &&
+ Line.startsWith(tok::kw_enum));
if (Style.Language == FormatStyle::LK_Proto && Left.isNot(tok::l_brace) &&
Right.is(TT_SelectorName))
return true;
@@ -2205,6 +2211,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Right.is(tok::r_paren) || Right.is(TT_TemplateCloser))
return false;
+ if (Right.is(tok::r_square) && Right.MatchingParen &&
+ Right.MatchingParen->is(TT_LambdaLSquare))
+ return false;
// We only break before r_brace if there was a corresponding break before
// the l_brace, which is tracked by BreakBeforeClosingBrace.
@@ -2265,7 +2274,8 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
const FormatToken *Tok = Line.First;
while (Tok) {
llvm::errs() << " M=" << Tok->MustBreakBefore
- << " C=" << Tok->CanBreakBefore << " T=" << Tok->Type
+ << " C=" << Tok->CanBreakBefore
+ << " T=" << getTokenTypeName(Tok->Type)
<< " S=" << Tok->SpacesRequiredBefore
<< " B=" << Tok->BlockParameterCount
<< " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName()
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index c58e6bccd9bc..97fd98ecb947 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -269,7 +269,14 @@ void UnwrappedLineParser::parseFile() {
void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
bool SwitchLabelEncountered = false;
do {
- switch (FormatTok->Tok.getKind()) {
+ tok::TokenKind kind = FormatTok->Tok.getKind();
+ if (FormatTok->Type == TT_MacroBlockBegin) {
+ kind = tok::l_brace;
+ } else if (FormatTok->Type == TT_MacroBlockEnd) {
+ kind = tok::r_brace;
+ }
+
+ switch (kind) {
case tok::comment:
nextToken();
addUnwrappedLine();
@@ -393,10 +400,16 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
bool MunchSemi) {
- assert(FormatTok->Tok.is(tok::l_brace) && "'{' expected");
+ assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
+ "'{' or macro block token expected");
+ const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
+
unsigned InitialLevel = Line->Level;
nextToken();
+ if (MacroBlock && FormatTok->is(tok::l_paren))
+ parseParens();
+
addUnwrappedLine();
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
@@ -405,12 +418,17 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
++Line->Level;
parseLevel(/*HasOpeningBrace=*/true);
- if (!FormatTok->Tok.is(tok::r_brace)) {
+ if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd)
+ : !FormatTok->is(tok::r_brace)) {
Line->Level = InitialLevel;
return;
}
nextToken(); // Munch the closing brace.
+
+ if (MacroBlock && FormatTok->is(tok::l_paren))
+ parseParens();
+
if (MunchSemi && FormatTok->Tok.is(tok::semi))
nextToken();
Line->Level = InitialLevel;
@@ -439,6 +457,8 @@ static bool ShouldBreakBeforeBrace(const FormatStyle &Style,
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
return InitialToken.isOneOf(tok::kw_namespace, tok::kw_class);
+ case FormatStyle::BS_Mozilla:
+ return InitialToken.isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union);
case FormatStyle::BS_Allman:
case FormatStyle::BS_GNU:
return true;
@@ -757,6 +777,11 @@ void UnwrappedLineParser::parseStructuralElement() {
parseForOrWhileLoop();
return;
}
+ if (FormatTok->is(TT_MacroBlockBegin)) {
+ parseBlock(/*MustBeDeclaration=*/false, /*AddLevel=*/true,
+ /*MunchSemi=*/false);
+ return;
+ }
if (Style.Language == FormatStyle::LK_JavaScript &&
FormatTok->is(Keywords.kw_import)) {
parseJavaScriptEs6ImportExport();
@@ -860,6 +885,11 @@ void UnwrappedLineParser::parseStructuralElement() {
parseTryCatch();
return;
case tok::identifier: {
+ if (FormatTok->is(TT_MacroBlockEnd)) {
+ addUnwrappedLine();
+ return;
+ }
+
// Parse function literal unless 'function' is the first token in a line
// in which case this should be treated as a free-standing function.
if (Style.Language == FormatStyle::LK_JavaScript &&
@@ -872,7 +902,7 @@ void UnwrappedLineParser::parseStructuralElement() {
FormatTok->is(Keywords.kw_interface)) {
parseRecord();
addUnwrappedLine();
- break;
+ return;
}
StringRef Text = FormatTok->TokenText;
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 01c56bdc4df9..57c97d0c312f 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -353,6 +353,7 @@ void ASTUnit::CacheCodeCompletionResults() {
// Translate global code completions into cached completions.
llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
+ CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);
for (Result &R : Results) {
switch (R.Kind) {
@@ -360,7 +361,7 @@ void ASTUnit::CacheCodeCompletionResults() {
bool IsNestedNameSpecifier = false;
CachedCodeCompletionResult CachedResult;
CachedResult.Completion = R.CreateCodeCompletionString(
- *TheSema, *CachedCompletionAllocator, CCTUInfo,
+ *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
IncludeBriefCommentsInCodeCompletion);
CachedResult.ShowInContexts = getDeclShowContexts(
R.Declaration, Ctx->getLangOpts(), IsNestedNameSpecifier);
@@ -423,7 +424,7 @@ void ASTUnit::CacheCodeCompletionResults() {
// nested-name-specifier completion.
R.StartsNestedNameSpecifier = true;
CachedResult.Completion = R.CreateCodeCompletionString(
- *TheSema, *CachedCompletionAllocator, CCTUInfo,
+ *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
IncludeBriefCommentsInCodeCompletion);
CachedResult.ShowInContexts = RemainingContexts;
CachedResult.Priority = CCP_NestedNameSpecifier;
@@ -444,7 +445,7 @@ void ASTUnit::CacheCodeCompletionResults() {
case Result::RK_Macro: {
CachedCodeCompletionResult CachedResult;
CachedResult.Completion = R.CreateCodeCompletionString(
- *TheSema, *CachedCompletionAllocator, CCTUInfo,
+ *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
IncludeBriefCommentsInCodeCompletion);
CachedResult.ShowInContexts
= (1LL << CodeCompletionContext::CCC_TopLevel)
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 6b0fed676182..ff041a8ec431 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -405,7 +405,7 @@ void CompilerInstance::createPCHExternalASTSource(
}
IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
- StringRef Path, const std::string &Sysroot, bool DisablePCHValidation,
+ StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
const PCHContainerOperations &PCHContainerOps,
void *DeserializationListener, bool OwnDeserializationListener,
@@ -413,7 +413,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
- PP, Context, PCHContainerOps, Sysroot.empty() ? "" : Sysroot.c_str(),
+ PP, Context, PCHContainerOps, Sysroot.empty() ? "" : Sysroot.data(),
DisablePCHValidation, AllowPCHWithCompilerErrors,
/*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders,
UseGlobalModuleIndex));
@@ -497,12 +497,14 @@ void CompilerInstance::createCodeCompletionConsumer() {
}
void CompilerInstance::createFrontendTimer() {
- FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
+ FrontendTimerGroup.reset(new llvm::TimerGroup("Clang front-end time report"));
+ FrontendTimer.reset(
+ new llvm::Timer("Clang front-end timer", *FrontendTimerGroup));
}
CodeCompleteConsumer *
CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
- const std::string &Filename,
+ StringRef Filename,
unsigned Line,
unsigned Column,
const CodeCompleteOptions &Opts,
@@ -1237,13 +1239,18 @@ void CompilerInstance::createModuleManager() {
HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
std::string Sysroot = HSOpts.Sysroot;
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
+ std::unique_ptr<llvm::Timer> ReadTimer;
+ if (FrontendTimerGroup)
+ ReadTimer = llvm::make_unique<llvm::Timer>("Reading modules",
+ *FrontendTimerGroup);
ModuleManager = new ASTReader(
getPreprocessor(), *Context, *getPCHContainerOperations(),
Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation,
/*AllowASTWithCompilerErrors=*/false,
/*AllowConfigurationMismatch=*/false,
HSOpts.ModulesValidateSystemHeaders,
- getFrontendOpts().UseGlobalModuleIndex);
+ getFrontendOpts().UseGlobalModuleIndex,
+ std::move(ReadTimer));
if (hasASTConsumer()) {
ModuleManager->setDeserializationListener(
getASTConsumer().GetASTDeserializationListener());
@@ -1259,6 +1266,11 @@ void CompilerInstance::createModuleManager() {
}
bool CompilerInstance::loadModuleFile(StringRef FileName) {
+ llvm::Timer Timer;
+ if (FrontendTimerGroup)
+ Timer.init("Preloading " + FileName.str(), *FrontendTimerGroup);
+ llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
+
// Helper to recursively read the module names for all modules we're adding.
// We mark these as known and redirect any attempt to load that module to
// the files we were handed.
@@ -1418,6 +1430,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
for (auto &Listener : DependencyCollectors)
Listener->attachToASTReader(*ModuleManager);
+ llvm::Timer Timer;
+ if (FrontendTimerGroup)
+ Timer.init("Loading " + ModuleFileName, *FrontendTimerGroup);
+ llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
+
// Try to load the module file.
unsigned ARRFlags =
Explicit ? 0 : ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index dd664ca652f0..6f13faf573be 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -508,6 +508,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions);
+ Opts.PrepareForLTO = Args.hasArg(OPT_flto);
+
Opts.MSVolatile = Args.hasArg(OPT_fms_volatile);
Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive);
@@ -555,6 +557,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_fsanitize_coverage_8bit_counters);
Opts.SanitizeMemoryTrackOrigins =
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
+ Opts.SanitizeMemoryUseAfterDtor =
+ Args.hasArg(OPT_fsanitize_memory_use_after_dtor);
Opts.SSPBufferSize =
getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags);
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
@@ -1647,6 +1651,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Check if -fopenmp is specified.
Opts.OpenMP = Args.hasArg(options::OPT_fopenmp);
+ Opts.OpenMPUseTLS =
+ Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
// Record whether the __DEPRECATED define was requested.
Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro,
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index 4a8a8a029e79..2afd23fcb9e8 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/Action.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -61,9 +62,25 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
}
// We expect to get back exactly one command job, if we didn't something
- // failed.
+ // failed. CUDA compilation is an exception as it creates multiple jobs. If
+ // that's the case, we proceed with the first job. If caller needs particular
+ // CUDA job, it should be controlled via --cuda-{host|device}-only option
+ // passed to the driver.
const driver::JobList &Jobs = C->getJobs();
- if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
+ bool CudaCompilation = false;
+ if (Jobs.size() > 1) {
+ for (auto &A : C->getActions()){
+ // On MacOSX real actions may end up being wrapped in BindArchAction
+ if (isa<driver::BindArchAction>(A))
+ A = *A->begin();
+ if (isa<driver::CudaDeviceAction>(A)) {
+ CudaCompilation = true;
+ break;
+ }
+ }
+ }
+ if (Jobs.size() == 0 || !isa<driver::Command>(*Jobs.begin()) ||
+ (Jobs.size() > 1 && !CudaCompilation)) {
SmallString<256> Msg;
llvm::raw_svector_ostream OS(Msg);
Jobs.Print(OS, "; ", true);
diff --git a/lib/Frontend/PCHContainerOperations.cpp b/lib/Frontend/PCHContainerOperations.cpp
index fd3278b3b145..c749bb5c8db4 100644
--- a/lib/Frontend/PCHContainerOperations.cpp
+++ b/lib/Frontend/PCHContainerOperations.cpp
@@ -18,8 +18,6 @@
#include "clang/Lex/ModuleLoader.h"
using namespace clang;
-PCHContainerOperations::~PCHContainerOperations() {}
-
namespace {
/// \brief A PCHContainerGenerator that writes out the PCH to a flat file.
diff --git a/lib/Headers/Intrin.h b/lib/Headers/Intrin.h
index 7ba311ea4b94..24b3eae8bf86 100644
--- a/lib/Headers/Intrin.h
+++ b/lib/Headers/Intrin.h
@@ -513,47 +513,40 @@ _BitScanReverse(unsigned long *_Index, unsigned long _Mask) {
return 1;
}
static __inline__ unsigned short __DEFAULT_FN_ATTRS
-__popcnt16(unsigned short value) {
- return __builtin_popcount((int)value);
+__popcnt16(unsigned short _Value) {
+ return __builtin_popcount((int)_Value);
}
static __inline__ unsigned int __DEFAULT_FN_ATTRS
-__popcnt(unsigned int value) {
- return __builtin_popcount(value);
+__popcnt(unsigned int _Value) {
+ return __builtin_p